文章目录
本质上,Qt Designer的ui文件是一个以XML格式书写的文件,文件中内容描述了一个界面的widget关系树。这个文件在以下两种情况下会使用到:
uic完成。QUiLoader类处理,该类用于解析XML文件并动态构造widget树。本文描述第一种情况:在编译的时候使用ui文件。描述ui文件背后的机制,以及如何在应用程序中使用设计好的ui文件。
在实际项目开发中,使用Qt Designer创建用户界面组件(当然也完全可以使用代码描述),并使用Qt的集成构建工具qmake和uic在构建应用程序时为生成代码,这个过程是集成开发环境完成的。生成的代码包含了ui文件中描述的用户界面对象,它是一个c++结构体,包含以下几个内容:
setupUi()的成员函数,用于在父部件上构建部件树。retranslateUi()的成员函数,用于处理ui文件字符串属性的转换。生成的代码可以在应用程序中包含,并可以直接使用。除此之外,还可以用于扩展标准小部件的子类。
了解了QtCreator对ui文件背后的处理机制,下文将来看看如何在编译构建过程中使用ui文件。
主要有三种方法在编译过程中使用ui文件:1、直接附加、2、单继承方式、3、多继承方式。
1、直接附加:构造一个小部件作为组件的占位符,并在其中设置用户界面。
2、单继承方式:子类化Qt标准界面元素的基类(例如QWidget或QDialog),并包括ui用户界面对象的私有实例。
3、多继承方式:将ui文件的基类和表单的用户接口对象都子类化。这允许从子类的范围内直接使用ui文件中定义的小部件。
此处,创建一个名为widget.ui的ui文件:

为了使用直接附加的方法使用ui文件,直接在main.cpp中包含ui_widget.h文件:
#include "ui_widget.h"
然后在主函数中构造一个标准的QWidget,用于创建widget小部件,我们则使用这个QWidget来托管由widget描述的用户界面ui文件,完整代码如下:
#include "ui_widget.h"
int main(int argc,char *argv[])
{
QApplication app(argc,argv);
QWidget *w = new QWidget;
Ui::Widget ui;
ui.setupUi(w);
w->show();
return app.exec();
}
直接附加方法是一种在应用程序中快速使用组件的简单方法。但是在实际开发中,使用Qt Designer创建的组件通常需要与应用程序的其余代码进行紧密的集成。例如,上面提供的widget代码将编译并运行,但是界面中的对象之间不会进行交互。为了实现这一点,则需要使用单继承方法。
使用单继承方式,需要子类化一个标准的Qt小部件,并在其中包括ui用户界面对象的私有实例。可以采取以下两种方式的任意一种:
(1)成员变量方式
(2)指向成员变量的指针
『成员变量方式』
在这种方法中,子类化了一个Qt小部件,并从构造函数中setupUi()用户界面。以这种方式使用的组件将ui文件中使用的小部件和布局公开给Qt小部件子类,并提供一个标准系统,用于在用户界面和应用程序中的其他对象之间建立信号和槽函数连接。
为了确保可以正常使用用户界面,需要在子类化的Qt小部件描述文件中包含uic生成的头文件,然后引用Ui::Widget(本文是Widget.ui界面文件):

子类化了一个Qt小部件子类的构造函数通过调用ui对象的setupUi()函数来构造和配置界面中的所有小部件和布局:

这种方法的优点是:简单使用继承来提供了基于QWidget的接口,并将用户界面小部件变量封装在ui数据成员中。我们可以使用这个方法在同一个小部件中定义多个用户界面,每个界面都包含在自己的名称空间中,并可以覆盖(或组合)它们。
『指向成员变量的指针』
采用这种方式,对ui用户界面对象的写法上就变成了指向Ui::Widget的指针:

对应的源文件则是:

这种方法的优点是:用户界面对象可以预先声明,这意味着不必在头文件中包含生成的ui_Widget.h文件,然后可以在不重新编译相关源文件的情况下更改ui文件。
可见,这两种方法都能使用ui文件,但推荐使用指向成员变量的指针的方式使用ui文件,这也是库和大型应用程序开发的方法,况且使用QtCreator新文件创建向导添加的ui界面类则是以这种方式生成的代码。
使用Qt Designer创建的ui文件可以与标准的基于QWidget的类一起子类化。通过这种方法,可以在子类的范围内直接访问ui文件中定义的所有用户界面组件,并能够使用connect()函数建立信号和槽函数连接。
本文创建了Widget.ui界面描述文件,首先则需要在子类中包含使用uic从Widget生成的头文件:
#include "ui_widget.h"
接着在这个类的定义中需继承QWidget和Ui::Widget,可以私有的继承Ui::Widget,以确保用户界面对象在子类中是私有的。当然还可以将其与public或protected关键字一起继承,就像在前面的例子中可以让ui为public或protected一样。如下所示:

对应的源码文件则是:

在多继承方式中,用户界面中使用的小部件的访问方式与手工在代码中创建的小部件的一样。除此之外,我们不再需要ui前缀来访问这些小部件了。
以上三种在进行应用程序编译时使用ui文件的方法,其目的都是以如何在应用程序设计和编写中使用UI文件中所描述的Widget为目的展开的。直接附加方法较为简单,在开发几乎不使用。单继承方式较为常用,其次是多继承方式。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi