FreeOZ论坛

标题: qt学习笔记 [打印本页]

作者: 四香油饼    时间: 8-1-2009 10:04
标题: qt学习笔记
回国前开始想学习qt,因为底子太差,很多基础的东西都不懂,先补习了一下c++(原来只看过一遍谭浩强,没实际编过程序),然后发现有些东西比如gcc等都跟linux关系很密切,没接触过linux的我经常看得一头雾水,又转头去从0开始学习linux,回了国以后,天天灯红酒绿,就扔一边了,现在回来重新开始。

现在开始跟着tutorial一步一步学习。把学习过程在这里记录一下,主要也是让大家也监督一下,要不自己容易偷懒。

扔了2个月,倒好像突然开了点窍,之前一直没能想明白的一个问题,现在突然明白了。回国前我用eclips+qt design,作了几个试验,发现在环境中都能运行,但是如果我从windows里面单独运行,总是说找不到dll文件,想了很久没相通。 今天直接用文本编辑器把那个就一个按钮的hello world写了一下,然后从命令行编译,运行,成功了!后来我从windows里面试图运行,结果又出现了同样的没有dll的错误信息,这时候我突然醒悟,原来是环境设置的问题,在命令行窗口,初始化时已经自动设置了路径,但是从windows里面直接运行,则缺少了这个设置,于是就找不到文件了。gcc的编译,似乎并不能把所有需要的库函数放到一个可执行文件里,所以存在着一个路径设置的问题。不知道linux下面是什么情况,以后用到再说吧。

顺便说一下,各位高人看到我有什么理解错误的地方,请及时给我指出来啊
作者: 四香油饼    时间: 8-1-2009 11:06
放错地方了,麻烦斑竹给挪到软件那里吧
作者: migao21    时间: 8-1-2009 13:00
你把qt和gcc按照bin的这个目录路径 加到windows环境变量path去, 就可以直接运行了。

linux下面也是一样的,都是加到用户的环境变量里面去。 当然linux下面用lib(.a)文件有时要指定。
作者: migao21    时间: 8-1-2009 13:03
我搞不懂lz为何要学qt呢, qt粉丝不要打我, 我觉得现在都是java, .net大行其道, 至少我认为在这里悉尼没有很多, 几乎没有。
作者: 四香油饼    时间: 8-1-2009 15:37
原帖由 migao21 于 8-1-2009 14:03 发表
我搞不懂lz为何要学qt呢, qt粉丝不要打我, 我觉得现在都是java, .net大行其道, 至少我认为在这里悉尼没有很多, 几乎没有。



一直想学习pc上的编程,曾经学习了一段时间的delphi,结果学了以后发现根我工作中的c混到了一起,c程序里经常冒出delphi的句子来,反过来也是,把自己搞晕了,就没再继续。后来决定还是c++吧,起码差不多。又跟着c++ builder走了一阵,但发现这个只能在windows下用,我的目标是嵌入式,还是linux有用一些,qt跨平台,正好适合我。


顺便做个笔记:

看到第5章了,可以用继承QWidget的方式自己定义一个类(window),然后把button等等东西都放在里面(在构造函数里面定义,parent widget是this, 使用new)
qApp是一个QApplication头文件里定义的全局变量,指向这个QApplication的对象(QApplication对象是每个程序必须有的,main函数里面第一句就是定义这个对象),qApp可以在任何地方使用,从而可以做到使用任何一个按钮作为程序的退出按钮。

疑问:如果定义2个QApplication对象会有什么结果? 比如分别为 App1和App2, 现在标准程序里面 main函数最后一句是 return App1.exec(); 如果还有个 App2, 在return语句之前, 加个 App2.exec();, 会有什么结果?

试了一下,程序如下:
int main (int argc, char * argv[])
{
        QApplication App(argc, argv), App2(argc, argv);
        ....(省略)
App2.exec();
        return App.exec();
}
编译能通过,一运行报告一个runtime error, "This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information"

看来只能有一个,我就不管为什么了,不是我这初级选手关心的问题,感兴趣的高手可以告诉俺一下。

[ 本帖最后由 四香油饼 于 8-1-2009 16:43 编辑 ]
作者: ubuntuhk    时间: 8-1-2009 16:05
我也不懂QT,但是看你上面这段说明,感觉是你在一个程序里面定义并使用两个QApp导致发生错误,就像你要往一个蚂蚁窝里面放两只蚁后也会出乱子一样。
作者: coredump    时间: 8-1-2009 16:45
标题: 回复 #5 四香油饼 的帖子
QApplication 这样的类是典型的Singleton Pattern的实现,目的就是防止你这类的突发奇想的用法的

参考:qt\src\corelib\kernel\qcoreapplication.h 里有个
class QCoreApplication
{
...
static QCoreApplication *instance() { return self; }
...
}

而QApplication是从QCoreApplication继承来的。

多看看QT的源代码,就明白了。QT源代码里几乎包含了所有经典Design Pattern的实做,静下心来研究会获益匪浅的

有一本书,专门结合QT4的源代码探讨C++设计模式实现和应用的,LZ不妨一读。
作者: coredump    时间: 8-1-2009 16:47
现在考你一下,你说那个报错是你第一个QApplication.exec()报的还是后一个报的,为什么报这样的错误? 如果不看代码,不调试就能知道原因,你就真正理解QApplication的实现原理了。
作者: coredump    时间: 8-1-2009 17:22
原帖由 migao21 于 8-1-2009 13:03 发表
我搞不懂lz为何要学qt呢, qt粉丝不要打我, 我觉得现在都是java, .net大行其道, 至少我认为在这里悉尼没有很多, 几乎没有。

这不矛盾的, C++, Java, C#各有各的应用领域。

对于QT来说,学它的目的可以是:

1. 开发手机应用
    Nokia收购了QT,并且移植到了S60系统上,此外Trolltech原来就有个基于Linux的Qtopia嵌入式平台(现在叫QT Extented)。Nokia最新的高端手机N97(http://www.freeoz.org/forum/redirect.php?fid=7046&tid=810290)里大量采用了QT进行开发。
2. Linux,Open Source开发
    如果在Linux下开发GUI程序的话,KDE, QT怎么能够不好好学习呢。
3. 大量的企业专业应用软件使用QT开发的
    http://trolltech.com/qt-in-use
    比如Mathematica , Google Earth, 西门子大量工控软件(http://trolltech.com/qt-in-use/story/customer/siemens), 一些高级复杂的可视化专业软件,如 MAYA等。如果需要开发类似系统,那么QT,C++必须非常精通。
4. 很多游戏的前端使用QT开发的

blablabla...
作者: 四香油饼    时间: 8-1-2009 18:17
原帖由 coredump 于 8-1-2009 17:47 发表
现在考你一下,你说那个报错是你第一个QApplication.exec()报的还是后一个报的,为什么报这样的错误? 如果不看代码,不调试就能知道原因,你就真正理解QApplication的实现原理了。


我其实不懂,你给的连接我也没看,觉得我现在应该集中精力能用起来再说,kernel的东西以后有时间需要提高水平的时候再慢慢学习。我瞎猜一个,应该是第一个吧?第二个生成的时候要求第一个终止,对于第一个相当于是受到外力的作用被迫中止,于是就报错了。
作者: coredump    时间: 8-1-2009 18:27
标题: 回复 #10 四香油饼 的帖子
非也。
第一个是自然终止的,正常结束。因为QApplication是单例模式的类,所以系统里只能有一个QApplication 实例,第一个和第二个其实都是同一个对象(不止两个,声明多少个QApplication其实系统里只有一个实例)。exec()本身也是个静态函数,这个函数结束后QApplication的这个唯一实例会被销毁,这样第二个exec()再执行时会发现那唯一的一个QApplication对象已经不见了,所以会报这样的错,这就是错误信息的 unusual way的含义。

不过你换个写法,程序就应该能够通过了:
        QApplication App1(argc, argv);
        App1.exec();
        QApplication App2(argc, argv);
        App2.exec();
作者: 四香油饼    时间: 8-1-2009 18:58
原帖由 coredump 于 8-1-2009 19:27 发表
非也。
第一个是自然终止的,正常结束。因为QApplication是单例模式的类,所以系统里只能有一个QApplication 实例,第一个和第二个其实都是同一个对象(不止两个,声明多少个QApplication其实系统里只有一个实例)。e ...



俺的理解,这是不是相当于程序运行了2次?第二个app只有在第一个结束之后才会运行
作者: coredump    时间: 8-1-2009 19:52
标题: 回复 #12 四香油饼 的帖子
看看结果就知道了
作者: 四香油饼    时间: 8-1-2009 23:08
试了,可以运行,但是退出的时候还是报那个错误。
作者: coredump    时间: 8-1-2009 23:16
标题: 回复 #14 四香油饼 的帖子
一般这样的错误都是内存操作引起的,比如一块内存被释放2次之类的,你用debug版运行,然后就能定位到位置了。QApplication类里面有很多的初始化细节,  不同平台上结果可能也不一样。

不过,源码面前,了无秘密
作者: 四香油饼    时间: 8-1-2009 23:50
太高深了,我先继续学习基本编程,等我能做出个正经程序来再说
作者: 四香油饼    时间: 9-1-2009 15:30
今天看了自己第7章,这个,http://doc.trolltech.com/4.4/tutorials-tutorial-t7.html 自己定义widget这块,其他地方都比较好懂,但是不太明白为什么头文件中定了一signals

signals:
     void valueChanged(int newValue);

但是却找不到valueChanged这个函数的内容呢?高人帮我解答一下吧。还有个问题,signal的名字可以自己随便起吗?

更新:
我找了了解释,Signals are automatically implemented in the meta-object file. signal是自动实现的,这里我又有了疑问,既然是自动实现的,就肯定需要遵守一定的规则吧?比如命名、数据类型什么的,都有哪些规则呢?

还有,signal的使用,也不是很清楚,例子中
      connect(slider, SIGNAL(valueChanged(int)),
             lcd, SLOT(display(int)));
    connect(slider, SIGNAL(valueChanged(int)),
             this, SIGNAL(valueChanged(int)));
第一句中,什么地方把slider的新值传递给slot的呢?还是说这个connect函数本身就是其这个作用的,只要SIGNAL()和SLOT()这两个括号中的数据类型是一致的就可以配对使用呢?如果是这样,我是否可以控制SIGNAL送出的数据呢?比如在第二句中,当slider值改变这个信号来的时候,我让this发出一个比如时间或者别的信号,能不能这么做呢?

请高手解答以下,多谢,这里有点糊涂。

[ 本帖最后由 四香油饼 于 9-1-2009 16:51 编辑 ]
作者: migao21    时间: 9-1-2009 16:25
signal就是信号, 这个是qt里面类似消息转递机制
每一个Qt对象都有signals(发送消息)和slots(接收消息)。

connect(slider,                               SIGNAL(valueChanged(int)),    lcd,         SLOT(display(int)));
slider  这个是你的控件对象   
SIGNAL(valueChanged(int)) 这个是你控件对象触发信号, 看名字就是在slider值变化的时候会触发。
lcd,这个是你要触发对象
SLOT(...)就是你要做的触发对象的事情函数。

connect就是把slider的事件和lcd的事件联系起来了:
当slider的value改变了, 就会触发对象lcd的display函数, 2个int参数也传递。
作者: migao21    时间: 9-1-2009 16:37
原帖由 coredump 于 8-1-2009 18:22 发表

这不矛盾的, C++, Java, C#各有各的应用领域。

对于QT来说,学它的目的可以是:

1. 开发手机应用
    Nokia收购了QT,并且移植到了S60系统上,此外Trolltech原来就有个基于Linux的Qtopia嵌入式平台(现在叫Q ...


我还真不知道qt那么强大呢。  看来我也要好好学习qt了。
作者: 四香油饼    时间: 9-1-2009 17:14
标题: 回复 #18 migao21 的帖子
但我如何知道传递的就是slider的值呢?如果我自己定义一个signal,又如何知道它传递什么值呢?
作者: migao21    时间: 9-1-2009 18:43
   
(1)  connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
(2)  connect(slider, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
第一句中,什么地方把slider的新值传递给slot的呢?还是说这个connect函数本身就是其这个作用的,只要SIGNAL()和SLOT()这两个括号中的数据类型是一致的就可以配对使用呢?如果是这样,我是否可以控制SIGNAL送出的数据呢?比如在第二句中,当slider值改变这个信号来的时候,我让this发出一个比如时间或者别的信号,能不能这么做呢?

(1)中, slider的valueChanged的时候就会把int值传给slot display函数

假设一个下拉框在mainwindow里面,同时还有一个文本行,定义如下:
QComboBox *QCB_abc;
QTextEdit *QTE_abc;

下拉框QComboBox控件有以下signal函数,可以直接调用
void QComboBox::currentIndexChanged ( const QString & text )   [signal]

你在mainwindow里面定义slot函数display(const QString & text )
void mainwindow::display(const QString & text )
{
    QTE_abc->setText (text ); // show the text of combo box to mainwindow
}

在mainwindow的构造函数里面, 有以下语句:
// 实例化QCB_abc
// 添加下拉框QCB_abc里面的内容
// 实例化QTE_abc

connect(QCB_abc, SIGNAL(currentIndexChanged (const QString & text )), this, SLOT(display()));
....

在运行以后,出现mainwindow,里面有个下拉框和文本框, 当你改变下拉框的值得时候, 改变的值会出现在文本框里面。

(2) 你不可以将一个signal传给另外一个signal, 信号只是信号, 并不触发任何事件, 你需要调用slot函数来触发事件。

不同控件有哪些signal可以直接用,或者有哪些现成的slot函数可以直接调用,你可以直接查qt帮助文档。
作者: coredump    时间: 9-1-2009 21:11
标题: 回复 #17 四香油饼 的帖子
先看看QT文档的信号槽机制原理相关的章节,这是QT最核心的特性之一,必须完全理解才能继续:
http://doc.trolltech.com/4.4/signalsandslots.html
作者: tkl888    时间: 9-1-2009 21:29
等找到工作后有时间学C++的时候就跟着搂主混了。
作者: atelier    时间: 9-1-2009 21:33
油饼我觉得你有时间不如学学C#的编程,可比QT有用多了,玩玩visual studio。

作者: coredump    时间: 9-1-2009 23:03
建议LZ同时学 C#, C++, Java, Objective-C 正好四箱油饼
作者: tkl888    时间: 9-1-2009 23:27
how about D language
作者: 四香油饼    时间: 9-1-2009 23:44
原帖由 migao21 于 9-1-2009 19:43 发表

(1)中, slider的valueChanged的时候就会把int值传给slot display函数

假设一个下拉框在mainwindow里面,同时还有一个文本行,定义如下:
QComboBox *QCB_abc;
QTextEdit *QTE_abc;

下拉框QComboBox控件有 ...


谢谢migao, signal传给signal,是那个例子里的阿,所以我糊涂呢,你看 http://doc.trolltech.com/4.4/tut ... 7-lcdrange-cpp.html
作者: 四香油饼    时间: 9-1-2009 23:47
原帖由 coredump 于 9-1-2009 22:11 发表
先看看QT文档的信号槽机制原理相关的章节,这是QT最核心的特性之一,必须完全理解才能继续:
http://doc.trolltech.com/4.4/signalsandslots.html


我听你的,先去看这个吧,搞清楚了再往下看
作者: coredump    时间: 10-1-2009 11:17
标题: 回复 #26 tkl888 的帖子
D设计上很不错,致力于C++的改良。不过貌似社区很不活跃,纯粹用着学来玩还是很有趣的。很多特性真的让人眼前一亮
作者: 四香油饼    时间: 12-1-2009 20:54
今天学习了一些有关singal/slot的进一步的知识,现在根据自己的理解做个总结:

1. 自定义类如果需要使用signal/slot,必须在类中最开始加上 Q_OBJECT 说明
2。signal函数不用自己实现,只需要写出定义就行了,前面加上signals:关键字
signals:
    void ValueChanged(int value);
3. signal的使用,在需要发出singal的地方,用emit关键字,
  emit ValueChanged(xxxx);
4.signal/slot 可以有任意多个任意类型的参数,而且可以想连接的2个参数数量可以不一致。(这个请专家指导一下,比如signal发出2个参数,第一个是int 第二个是 char*,slot只有一个char*,能配对吗?)
5。slot像调用函数,connect语句后面的程序只有等slot执行完成后,才会继续执行(除非使用queueed connections)
6。signal/slot需要使用翻译成标准的c++才能编译,可以通过qmake实现,具体细节我先不细看了。
7。当一个slot同时接受多个signal时,可以由QSignalMapper来区分signal来源,我先跳过细节,用到再看。
作者: coredump    时间: 12-1-2009 21:02
关于4,这个其实和C/C++的函数调用是一样的。函数调用的参数个数可以不和函数的定义一致。但是不鼓励这样的行为,容易出现未定义的错误。而且根据编译器和编译参数的不同,这样的行为可能被给出警告或者错误。

另外, QT中还可以把2个signals连起来, 不一定是signal和slot. 在QT4以前,signal和slot必须处在同一个thread中,现在没有这个限制了,可以跨thread进行signal/slot连接
作者: coredump    时间: 12-1-2009 21:11
关于signal/slot机制,其实是一种很通用的解偶方法。C++的signal/slot实现出了QT这个比较有名以外,还有boost实现(http://www.boost.org/doc/libs/1_37_0/doc/html/signals.html),sigslot(http://sigslot.sourceforge.net/)等. 其中那个sigslot是个专门实现c++ signal slot机制的库。像Google Talk的libjingle API (http://code.google.com/intl/zh-C ... eveloper_guide.html)就使用了这个库。
作者: migao21    时间: 12-1-2009 21:28
原帖由 coredump 于 12-1-2009 22:02 发表
关于4,这个其实和C/C++的函数调用是一样的。函数调用的参数个数可以不和函数的定义一致。但是不鼓励这样的行为,容易出现未定义的错误。而且根据编译器和编译参数的不同,这样的行为可能被给出警告或者错误。

另 ...



受益匪浅,谢谢
作者: 四香油饼    时间: 13-1-2009 08:36
qt网站改名了,原来的trolltech.com自动跳转到了qtsoftware.com
作者: 清风不写字    时间: 13-1-2009 11:41
不熟悉C++,路过。
作者: 四香油饼    时间: 13-1-2009 12:02
原帖由 清风不写字 于 13-1-2009 12:41 发表
不熟悉C++,路过。



厚厚,好久不见阿,别来无恙乎?
作者: 四香油饼    时间: 13-1-2009 15:08
今天回到继续跟着教程学习的路上。学习了第7章,第8章,不过第8章还没理解透彻。关于PaintEvent的概念还不是很清楚。

前面的概念基本清楚后,第7章就非常容易理解了,我看了其大概的内容,觉得比较好理解,决定不看例子,完全自己写一个类似功能的程序。

把原来的单个hello.cpp分成了几个文件,my_lcd.h头文件,用来定义my_lcd类,其具体构造函数和内部函数放在my_lcd.cpp中。记得谭浩强的书里看到过,这种把头文件和具体函数分开的方法,除了可以让结构清晰外,还可以将cpp文件编译成独立的库,可以把头文件和编译好的库提供给买家使用,而不必公开具体的实现代码。原来使用c语言时从来没有注意过这些,今后尽量锻炼自己写出结构优美的程序。

实际写的过程不太顺利,主要原因是对c++还是不够熟悉,比如派生类的定义的句法经常出错,看来还要多写,熟能生巧。另外Qt本身的类及其函数不太清楚,函数名称搞错了不少,不得以还是看了例子程序,实际作程序的话应该使用designer一类的工具应该就好多了吧,不过看来要想用好qt,必须对其提供的各种widget有个概括的了解,起码大致知道各种widget能做什么,不能做什么。

最后作了个这样的程序,用lcd和slider组成一个自定义widget,放在一个layout里面,然后再将5个widget以及一个lcd和一个按钮放在一个layout中,形成2层layout的结构,外面这层的lcd随着最后一组slider的变化而变化。
作者: 四香油饼    时间: 15-1-2009 22:19
者两天一下子忙起来了,上班没什么时间看qt乐。不过还是看了一点点。

没有继续跟着tutor向下走,因为感觉到有些基本概念不是特别清晰。看了看QWidget的文档,因为差不多所有的Widget都是从QWidget派生出来的,QWidget有的所有的Widget都应该有。我想对QWidget了解得多一些会有好处。

看了以后发现就一个QWidget经已经有无数的properties和functions, 不过看来大体可以分为几类,一个是有关外观的,什么窗口尺寸,位置,颜色字体一类的,再一类是有关事件的,鼠标、键盘等等的各种事件,了解了一下grab类的函数和事件的区别,知道了grab就相当于把事件拦截了,不再发给其他widget。

重点看了看paintEvent(),我的理解,paintEvent()是当窗口刷新的时候触发的,应该是在现有显示清掉,新的还没有画出之前。
Widget的刷新可以由update()函数引起,也可以由比如窗口的移动等引起。

具体的用法,后面的例子里面应该有吧。
作者: 四香油饼    时间: 20-1-2009 15:53
这些天工作忙了,晚上也没怎么学习,所以进度慢了。

对 event 还是不是特别清楚,因为例子里面只是使用了  paintEvent()这个event handler, 但是讲得很少,今天把qt文档中有关event的部分仔细看了看,才算稍微明白一点:

event 是由window环境或者程序自身发出的,qt里面,event也是一个类,通过event handler函数传递给widget, event handler是widget中已经定义好的虚函数,名称是固定的。我一开始没有弄明白的,就是这一点。event handler的大概格式是:
void QWidget::mouseMoveEvent(QMouseEvent *event)
通过event, 可以传递给widget各种信息,比如 event->x(), event->y()等。

如果我理解得不错的话,熟练掌握了Widget的各种属性和内建函数,以及event,就可以做一般的窗口应用程序了。

作为练习,我做了这个程序:颜色区域用了mouseMoveEvent,来得到鼠标的坐标,然后在paintEvent中显示出来,同时,把两者乘积作为signal发送给LCD
作者: 饭特稀,肾特虚    时间: 20-1-2009 16:28
标题: 玩C++的,仰慕一下
IT行业里面的高端人士,潜在的中产阶级。
未来少妇、师奶和妙龄少女围追堵截的对象。
作者: coredump    时间: 20-1-2009 19:14
标题: 回复 #40 饭特稀,肾特虚 的帖子
做梦都想有这待遇阿
作者: migao21    时间: 20-1-2009 20:14
我怎么觉得会qt,离c++还远着呢~~~
作者: someonehappy    时间: 21-1-2009 14:39
才知道有qt这么个东西。

可以这么理解么,基于C++的一个开发平台,而且在几个流行操作系统上都有类库支持。比较适合注重性能或者和系统地层结合比较紧密的系统的开发,看例子好多都是和图形图像多媒体处理,数学计算之类的有关。这正好是java不注重的地方。

不过貌似主页上也提到了界面开发的部分,以及对java的支持。

啥时候也来弄个玩玩。
作者: coredump    时间: 21-1-2009 16:33
标题: 回复 #43 someonehappy 的帖子
不过貌似主页上提到了界面开发的部分,以及对java的支持。

。。。。不是,QT最重要的身份就是C++ GUI Library.
作者: coredump    时间: 21-1-2009 16:43
原帖由 migao21 于 20-1-2009 20:14 发表
我怎么觉得会qt,离c++还远着呢~~~

感觉正确


和C++比较近的大都在用C++写QT这类的东东呢
作者: GPS    时间: 25-1-2009 21:27
GTK和Qt有什么比较吗?哪位高手讲讲。
作者: coredump    时间: 25-1-2009 22:58
标题: 回复 #46 GPS 的帖子
GTK - GIMP Tookit  , 是一个用C写成的GUI框架,是GIMP软件和GNOME桌面环境的基础

QT - KDE的基础,著名的跨平台C++ GUI框架
作者: GPS    时间: 26-1-2009 00:40
gtkmm是gtk的C++ 封装,从性能上比较,它和Qt有太多区别吗?
作者: coredump    时间: 26-1-2009 00:51
标题: 回复 #48 GPS 的帖子
gtkmm的封装不是很成功,基本上很少有Gnome项目是用gtkmm写的。 一般而言,这类在C上面做的C++wrapper都不是很受欢迎。

性能上, GTK 和QT各有千秋, 都有不少追随者。 QT的历史比较久一点,而且现在QT已经提供了和GTK一样的LGPL许可,很多批评QT的依据已经不复存在了,我更看好QT
作者: 绿衣    时间: 26-1-2009 15:39
标题: 回复 #9 coredump 的帖子
有个疑问,Q迷和N饭们不要拍我:既然QT被Nokia收购了,是不是意味着QT的命运跟Nokia绑到了一起?个人感觉N很可能会步Moto的后尘。可能我的感觉不对,欢迎指教。

因为现在的项目也在选GUI平台/框架(用C++语言),正在比较中,主要是不想花时间去学个命不长的东东。除了QT还有什么好推荐吗?要上手快,运行速度快。(MFC不谈)
作者: coredump    时间: 26-1-2009 20:51
标题: 回复 #50 绿衣 的帖子
有此疑问很正常,请Google "KDE基金会", 答案尽在其中
作者: coredump    时间: 26-1-2009 20:56
标题: KDE Free Qt基金会
FROM:http://www.kdecn.org/whatiskde/kdefreeqtfoundation.php
KDE Free Qt基金会成立于1998年,它由Trolltech公司KDE协会共同组建,其目的是促使Qt工具包可以为自由软件尤其是KDE桌面环境未来的开发提供有效的可持续性担保。
在Trolltech公司和本基金会间存在以下承诺,除非Trolltech公司被收购、合并或是破产,否则无论是出于什么因由,一旦Trolltech公司无法延续对Qt自由版本(Qt Free Edition)的开发,基金会被授权可以将Qt在BSD授权许可下重新发布。
在2004年5月本协议条款有所改动,新的条款替换了1998年6月的旧条款以适应当前的最新状况,这份新的文本更加明确和全面地阐述了具体操作中的一些问题,其中最重要的一项改变是,即使Trolltech公司因任何理由,甚至包括面临收购、合并或是财产清算而无法继续对Qt自由版本的开发时,本基金会仍然有权将Qt自由版本在BSD或是除此之外再附加一种或更多开源授权协议这样的条款下将其重新分发。除此以外,协议的本意和基本内容没有改变。
本基金会包括Trolltech和KDE协会的各两名成员,基金会的所有决议将由这四名成员投票产生,如果票数相同,则采纳KDE协会代表的意见为最终决定。
在KDE Free Qt基金会中两名来自KDE协会的委员为:
当前的Trolltech公司的投票代表(由Trolltech内部常务会议选举得出)为:

作者: coredump    时间: 26-1-2009 21:00
标题: 回复 #52 coredump 的帖子
而且Nokia收购TrollTech后,甚至增加了对商业开发更为友好的LGPL协议,使得QT可以进入更为广阔的软件开发领域。

在KDE Free QT基金会的协议里,甚至还有一条规定了QT的开发进度,如果不能在每xx(好像是12)月内推出新版本,基金会也有权把QT free到BSD License下。可以说在这样的规定下,QT已经不会受任何商业公司的绑架了,彻底Free而且发展有保障!
作者: coredump    时间: 26-1-2009 21:03
原帖由 绿衣 于 26-1-2009 15:39 发表
因为现在的项目也在选GUI平台/框架(用C++语言),正在比较中,主要是不想花时间去学个命不长的东东。除了QT还有什么好推荐吗?要上手快,运行速度快。(MFC不谈)


C++ GUI Framework大全, 自个儿选吧。
作者: 四香油饼    时间: 29-1-2009 09:38
core老师,有一个地方不太理解,请给指点一下呀:

自定义的widget里面,加的那一句 Q_OBJECT是个什么东西呢?怎么觉得不太符合c++语法呢?是个宏吗?这个语句的作用还是不太理解。

我搜了下资料,好像跟meta-object有关,这个meta-object又是什么含义呢?

[ 本帖最后由 四香油饼 于 29-1-2009 10:41 编辑 ]
作者: coredump    时间: 29-1-2009 17:17
标题: 回复 #55 四香油饼 的帖子
Q__OBJECT的确看起来怪怪的,是QT Meta-Object System相关的一个宏定义,Meta-Object System 是QT中的一个核心概念。QT文档中的doc/html/metaobjects.html对此有详细解释。

关于Meta-Object的简单解释:

C++是静态类型的编程语言,其类型信息只在编译时有效,一旦编译成可执行文件后,里面就只剩下一大堆汇编指令了,写在源代码的那些变量,类,方法,函数等等一切的符号信息便统统消失不见了,因为是强静态类型的语言,一旦编译完成,程序的行为便完全确定了,理论上是不需要这些符号信息的。虽然debug版的可执行程序含有这些符号,不过这并不是C++标准的一部分。

但是在GUI编程领域和很多现代的软件开发实践中(比如AOP, IoC, ORM等设计模式), 在程序运行时能够访问这些写在源代码里的符号信息有很大的用处。这些符号信息用计算机术语来说就叫元数据(meta data), 意思是不是一般的程序处理的数据,而是表示程序本身的数据。 而能够访问这些自身元数据的能力叫做自省(reflection), 典型的自省能力包括:

1.可以根据运行时提供的类名字生成对应的对象实例

对一个运行时对象,
2. 能知道自己的类型名字
3. 知道自己有多少数据成员以及他们的名字,类型,并且能够根据指定的名字字符串访问他们
4. 知道自己的所有方法,并且能够根据指定的方法名字符串动态调用它们
5. 知道自己的类继承体系:从哪继承(基类信息), 被谁继承(子类信息)等

对于C#和Java这样的语言来说做到上述几点要求不是难事,因为.NET运行时和JVM标准里已经包含的完整的元数据标准和访问这些元数据的API。 但是对于C++来说做到这些就颇为困难了,但这些能力对于一个强大的GUI框架来说又是如此的有诱惑力甚至不可或缺,于是QT就扩展了C++, 提供了一个C++的元对象系统, 并且在使用C++编译器编译前先用自己的moc(meta object compiler)编译器处理一边。这样QT就能在用C++的同时享用同样强大的元数据处理能力了。 这些能力主要用在了以下方面:
1. signal slot
2. QT的属性系统
3. QT的图形界面动态加载系统 (.ui文件和uic编译器,以及qt designer能)
4. QT的QSA (QT Script系统,用Javascript访问QT对象)
5. QT的单元测试系统

等等。 可以说,整个QT框架都是建立在这个meta object system只上的。


关于这个Q_OBJECT的实现细节可以用Visual Studio跟踪器定义,实际上就是个宏,和MFC中实现消息映射的一些宏类似, 就是为类增加了一个QMetaObject成员和访问这个成员的函数(如 metaObject()). QMetaObject定义了QT meta object system 所支持的所有操作,详情见其定义。
作者: 绿衣    时间: 30-1-2009 19:34
标题: 回复 #52 coredump 的帖子
还有这样的是,蛮有趣的。谢谢指教啦
作者: 四香油饼    时间: 2-2-2009 15:35
遇到了一个问题,百思不得其解,还请老师指点:

我想在我定义的Widget(里面包含一些按钮等)里面画一个图形,但是为什么编译报错呢?程序如下:

class MyWidget : public QWidget
{
        Q_OBJECT
        public:
        MyWidget(QWidget *parent=0);
        protected:
        void paintEvent(QPaintEvent *event);
        private:
        int i;
};

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
        QLCDNumber *Disp1 = new QLCDNumber;
        QPushButton *Button1 = new QPushButton("Quit");
        MyPaintArea *Area1 = new MyPaintArea;
        QVBoxLayout *Box1 = new QVBoxLayout;
        Box1->addWidget(Disp1);
        Box1->addWidget(Area1);
        Box1->addWidget(Button1);
        setLayout(Box1);
        connect(Button1, SIGNAL(clicked()), qApp, SLOT(quit()));
        connect(Area1, SIGNAL(AreaChanged(int)), Disp1, SLOT(display(int)));
}

void MyWidget::paintEvent(QPaintEvent *)
{
        QPainter *painter(this);
        painter.setBrush(Qt::blue);
        painter.drawRect(30,-30,10,10);
}

我的目的是想在MyWidget里面画一个方块,这个方块应该是覆盖在现有的内容(比如LCDNumber, PushButton等等)上面吧?你们看我的程序什么地方有问题呢? 编译总报错:
hello.cpp:38: error: cannot convert 'MyWidget* const' to 'QPainter*' in initialization

这个第38行就是那个
QPainter *painter(this); 语句
作者: coredump    时间: 2-2-2009 16:27
QPainter *painter(this);

should be :

QPainter painter(this);

or
QPainter *painter = new QPainter (this);
作者: 四香油饼    时间: 2-2-2009 17:01
哎,真是明眼人一眼就看看透,我怎么会犯这种低级错误呢,一开始想写指针那种形式,后来看例子里面是函数的,就改函数的了,但忘了前面的*号,居然还看了一下午看不出来,太笨了!
作者: coredump    时间: 2-2-2009 17:06
标题: 回复 #60 四香油饼 的帖子
很正常,一般出现这种情况的时候就表示该起身去喝杯咖啡了
作者: migao21    时间: 3-2-2009 09:17
所以说我觉得先打好c++基础才是王道。
作者: aud    时间: 3-2-2009 10:08
四香油饼,你看的是中文的书吗?
作者: 四香油饼    时间: 3-2-2009 10:23
原帖由 aud 于 3-2-2009 11:08 发表
四香油饼,你看的是中文的书吗?



不是,我看的是qt网站的英文的。不过我这次回国倒是带了2本中文的qt书回来,不过还没看。

新问题请教老师:

还是昨天那个程序,发现编译还是老通不过,错误信息是: in fuction 'ZN8MyWidgetC1EP7QWidget', hello.cp:23: undifined reference to 'vtable for MyWidget‘

经过反复检查后,发现如果把MyWidget定义中的'Q_OBJECT'去掉,就能通过了。这里我不太理解,Q_OBJECT不是‘使能’meta-object特性的吗?是否因为MyWidget里面没有用到signal/slot就不能加入Q_OBJECT呢?还是说其它的原因?
作者: migao21    时间: 3-2-2009 10:52
你只要用到QT类或者是继承QT类,都必须有Q_OBJECT

        
        QPainter *painter(this);
        painter.setBrush(Qt::blue);
        painter.drawRect(30,-30,10,10);

这里如果你实例化类用指针,后面要用->
        QPainter *painter = new QPainter (this);
        painter->setBrush(Qt::blue);
        painter->drawRect(30,-30,10,10);

但是根据你报错信息, 你有可能是某个类的.h文件未包含,或者是未声明。 不知道你hello.cp:23是哪一行?
作者: 四香油饼    时间: 3-2-2009 14:33
标题: 回复 #65 migao21 的帖子
指针那个问题我已经注意了,不是那个问题。现在的问题是去掉 Q_OBJECT那句,就通过了,运行也正确。我不理解的是为什么不能加上。

出错的一行是这个:
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{-------------------------------------------------------------------------------------------这一行是23行
        QLCDNumber *Disp1 = new QLCDNumber;
        QPushButton *Button1 = new QPushButton("Quit");
        MyPaintArea *Area1 = new MyPaintArea;
        QVBoxLayout *Box1 = new QVBoxLayout;
        Box1->addWidget(Disp1);
        Box1->addWidget(Area1);
        Box1->addWidget(Button1);
        setLayout(Box1);
        connect(Button1, SIGNAL(clicked()), qApp, SLOT(quit()));
        connect(Area1, SIGNAL(AreaChanged(int)), Disp1, SLOT(display(int)));
}
作者: coredump    时间: 3-2-2009 17:37
标题: 回复 #66 四香油饼 的帖子
你是把所有的东西都写在.cpp里的吧。 qmake解析.pro文件的时候是只对.h文件进行Q_OBJECT扫描的,如果找到了就调用moc xxx.h 从而生成moc_xxx.cpp并一起编译链接到最后的程序中。

如果Q_OBJECT是在.cpp中的, 你需要手工moc xxx.cpp, 生成的moc_xxx.cpp也需要放到.pro的SOURCE列表中。

避免出现此类问题的最好办法就是严格按照QT的开发规范来写程序, 类的声明放在.h文件中,类的实现放在.cpp文件中
作者: GPS    时间: 5-2-2009 11:10
我正在想学用GTK+(GTKMM)呢,还是Qt。GTK在GNOME的桌面下用,Qt是在KDE下,问题是如果有一些现有的东西是在GNOME下的,新的用QT是不是不好呢?

另外,Qt好像有liscense的限制吗?据说GTKMM用的是STL,而Qt用的是自己的container。是不是STL比较通用点呢?

请高手指点下啊
作者: coredump    时间: 5-2-2009 15:18
我正在想学用GTK+(GTKMM)呢,还是Qt。
-----用GTK最好不要用GTKMM,这是很不成熟的C++封装,大部分gtk程序使用c写出来的

GTK在GNOME的桌面下用,Qt是在KDE下
-----not at all, gnome上用qt一点事没有, kde下跑gtk也很正常。不过跨平台方面,QT比较有优势

问题是如果有一些现有的东西是在GNOME下的,新的用QT是不是不好呢?
----自己权衡利弊了

另外,Qt好像有liscense的限制吗?
---多看技术新闻,多qtsoftware.com的主页上看看,不要盯着N年前的老文章。或者好好看这个帖子,上面一层楼对这个问题说得很清楚了。

据说GTKMM用的是STL,而Qt用的是自己的container。是不是STL比较通用点呢?
---用了就知道了,QT的container不是stl,但是不排斥你在qt中使用stl,就像在MFC中不用CString而用std::string一样自然
作者: GPS    时间: 5-2-2009 20:58
谢谢coredump指点。

既然QT在GNOME上也没问题,那就OK了。
现在的问题就是原有的系统是用GTK和C,新加的用C++跟Qt是没问题了。主要是如果局部要改原来的,就要用Gtk了。看来两个都要学。
我是觉得做界面怎么也要用OO的东西,用C似乎笨了一点。而且好象Qt在游戏开发上也不错,不知道我理解对否。

COREDUMP真是高手啊,请问是在做哪个方面的东东呢?这里高手不少,以后一定多多请教。
作者: coredump    时间: 5-2-2009 21:39
标题: 回复 #70 GPS 的帖子
我现在整天写MFC
作者: GPS    时间: 6-2-2009 08:28
原帖由 coredump 于 5-2-2009 22:39 发表
我现在整天写MFC


高手做MFC是不是觉得不够过瘾啊?呵呵。

我看了一下Qt的Whitepaper,有几个问题请教,请各位高手指点一下。

Qt并不只是一个GUI的API, 里面包括了container,graphic,socket,database,整个基本都包括了application级别的构架。是不是可以说,我用Qt,即使不做GUI,也是可行而且有效的。基本上,做application的话就不用别的东西了,就象MFC?如果这样,那真是合算啊,学一个就基本够用了。

用了Qt是不是可以不用ACE了?因为Qt已经有socketle?

另外,如果在Linux下,用Qtdesigner好还是g++好呢?有什么比较建议吗?

谢谢。

[ 本帖最后由 GPS 于 6-2-2009 09:37 编辑 ]
作者: coredump    时间: 6-2-2009 10:28
高手做MFC是不是觉得不够过瘾啊?呵呵。
------- MFC很刺激的

Qt并不只是一个GUI的API, 里面包括了container,graphic,socket,database,整个基本都包括了application级别的构架。是不是可以说,我用Qt,即使不做GUI,也是可行而且有效的。基本上,做application的话就不用别的东西了,就象MFC?如果这样,那真是合算啊,学一个就基本够用了。
----QT 强项在GUI,很多基础设计(比如signal slot)都是为GUI量身定做的。不用GUI又要用QT的话可以用QT的server版,其实QT的各个组件都是很独立的,想用哪个模块就用哪个模块好了。

用了Qt是不是可以不用ACE了?因为Qt已经有socketle?
--- QT和ACE不是一个层面的东西,ACE是专注网络通讯方面的框架,在网络方面QT远不及ACE,不过要看情况决定,如果开发的应用不是对网络通讯要求非常苛刻,QT的网络模块还是很好用的,封装的让人感觉很舒服。而且结合QT4.4开始引进的Qconcurrent框架开发网络程序很自然。

另外,如果在Linux下,用Qtdesigner好还是g++好呢?有什么比较建议吗?
---     这两个东西有什么共同点吗?
作者: GPS    时间: 6-2-2009 19:56
Qtdesigner 是个Qt的IDE,如果不用它的话,是不是就要用命令行,用G++来编译。QtDesigner会自动生成一些code。我想问的是,这两种方式有什么优劣比较吗?或者是完全等同呢?
作者: GPS    时间: 6-2-2009 19:59
这里好象有不少Linux和Qt的高手及爱好者,版主是不是组织个Linux的group,定期见面讨论,学习下啊?对新手很有帮助的。呵呵。不过高手可能觉得浪费时间了。
作者: coredump    时间: 6-2-2009 20:03
标题: 回复 #74 GPS 的帖子
qtdesigner只是个qt的ui设计器,生成的是.ui的xml配置文件, 编译成代码的是uic编译器,就像moc一样是qt的一个辅助工具,和g++是完全两个不同层面的东西。

目前qtdesigner可以单独使用,也可以和vs或eclipse结合使用(商业版),也可以在qt最新推出的qt-creator中使用。
作者: GPS    时间: 6-2-2009 21:53
看来还是先学学,一步步做吧。
作者: GPS    时间: 18-2-2009 23:38
coredump -
我在学Qt4的database编程。
ubuntu 8。10, mysql。

#include <QSqlDatabase>
#include <QDebug>

int main(int argc, char **argv)
{

    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

    db.setHostName( "localhost");
    db.setDatabaseName("mydb");
    db.setUserName("root");
    db.setPassword("qyyqyy");

    if( !db.open() )
    {
        qDebug()<< db.lastError();
        qFatal( "Failed to connect.");
    }
}
编译-
qmake -project
qmake
make

错误-找不到QSqlDatabase.h,我加上目录 QSql/ 后,还是有编译错误,把   qDebug()<< db.lastError(); 注释后,编译通过,但是连接不行,就是DB的库没连上。
qt4安装在-
apt-get install libqt4...... 好几个package都装了,在/usr下

请问应该在哪里设置? 估计socket编程也要出类似问题。

非常感谢了。
作者: GPS    时间: 19-2-2009 09:20
已经解决了。
我在project file里加了 QT += sql , 在source code中 #inlucde<QSqlError>.
作者: GPS    时间: 19-2-2009 20:28
标题: 怎样debug Qt4?
哪位高手指点一下吧。谢谢了。
是不是要自己改Makefile?
作者: coredump    时间: 19-2-2009 20:57
标题: 回复 #80 GPS 的帖子
改.pro文件,编译为debug模式即可

http://doc.trolltech.com/4.4/qma ... g-and-release-modes
作者: 四香油饼    时间: 20-2-2009 08:34
老师,再问个问题:QT做出来的程序,能像c++ builder那样是一个单独的exe文件么?如果不是,如果想把程序给别人用,该怎么做呢?
作者: coredump    时间: 20-2-2009 10:24
标题: 回复 #82 四香油饼 的帖子
差不多都是一样的,一般一个.exe文件夹上QT的几个DLL就行了,如果要做安装包的话可以用各种制作软件安装包的工具制作
作者: 四香油饼    时间: 20-2-2009 14:48
老师:再请指点一下

这次请老师指点一下我下一步该向哪个方向学习。

通过一段时间的学习,我觉得我初步了解了qt编程的基础,对于一个应用程序来讲,可能剩下的就是一些具体的widget的应用了,比如各种按钮等等的,我想我的目的在于能够编写一些应用程序,我觉得我需要学的东西还有很多,不知道是不是应该在熟练应用这些widget的内建函数、属性的方面花费很多的时间,还是可以需要用哪个了再去查手册就好了。

因为我觉得我还得学习比如linux的基础等等,我希望能打下一个比较扎实的基础,但又不希望在细节上花费太多的时间,所以想请老师给我点建议,现在应该怎么做?
作者: valpa    时间: 20-2-2009 15:02
原帖由 四香油饼 于 8-1-2009 11:04 发表
回国前开始想学习qt,因为底子太差,很多基础的东西都不懂,先补习了一下c++(原来只看过一遍谭浩强,没实际编过程序),然后发现有些东西比如gcc等都跟linux关系很密切,没接触过linux的我经常看得一头雾水,又转头去 ...


葱油原来是IT的啊
作者: coredump    时间: 20-2-2009 21:21
原帖由 四香油饼 于 20-2-2009 14:48 发表
老师:再请指点一下

这次请老师指点一下我下一步该向哪个方向学习。

通过一段时间的学习,我觉得我初步了解了qt编程的基础,对于一个应用程序来讲,可能剩下的就是一些具体的widget的应用了,比如各种按钮等 ...


这个学期就这到这里吧,先把下学期学费交了再说

本学期作业:找个感兴趣的功能先做起来,在做中学,干学,学者学者就烦了,没有成就感。就像旅游,光读别人的游记,那留下来的印象和自己经历过的怎么能相比呢,对吧
作者: 四香油饼    时间: 20-2-2009 22:08
原帖由 coredump 于 20-2-2009 22:21 发表


这个学期就这到这里吧,先把下学期学费交了再说

本学期作业:找个感兴趣的功能先做起来,在做中学,干学,学者学者就烦了,没有成就感。就像旅游,光读别人的游记,那留下来的印象和自己经历过的怎么能相比 ...


成吧,老师说的肯定有道理,我回头编个小程序万万
作者: GPS    时间: 21-2-2009 21:23
四香油饼你找个题目吧,我也一起编编,互相学习把。
作者: 四香油饼    时间: 24-2-2009 15:21
原帖由 GPS 于 21-2-2009 22:23 发表
四香油饼你找个题目吧,我也一起编编,互相学习把。



这两天在想,想好了我写出来你看看
作者: GPS    时间: 28-2-2009 16:58
有问题,请高手指教。
QT4的内存管理问题。 是不是Q的widgets都是可以有系统直接释放内存? 只要new, 不用delete? 包括我自己的QObject的派生类? 那么,我在其中自己 new 的其它类, 打开的DB,FILE呢?应该在何时关闭?
一般在C++中,用DESTRUCTOR 来释放在类中动态分配的各种资源,那么在QT中怎么办呢? WIDGET本身可以有QT的reflection 结构来释放,可是WIDGET中用户再分配的其它资源呢? 我怎么没看到哪个例子中有DESTRUCTOR的。
高手指点指点吧。
作者: coredump    时间: 28-2-2009 21:32
标题: 回复 #90 GPS 的帖子
QT是采用很有特色的链式父子内存管理,每个对象都有个parent, 只要指定了parent的对象就不用担心内存的释放问题了,只要parent释放了会自动递归地释放它的所有子孙对象。
作者: GPS    时间: 28-2-2009 23:43
例子,
class A : public QDialog
{
      int *a ;
     A() { a = new int[100];}
}

Q1: A是QObject的子类,所以A一定可以被释放?
还是必须是调用A(parent) 或者 parent.addWidget(A的实例)来设定A的parent呢?
Q2:只要A被释放, a 就一定被释放?
作者: coredump    时间: 28-2-2009 23:47
标题: 回复 #92 GPS 的帖子
理解完全错误。

http://matzeswebblog.blogspot.co ... ment-in-object.html

http://doc.trolltech.com/4.5/objecttrees.html
作者: GPS    时间: 1-3-2009 00:05
我怎么觉得Q1已经说清楚了 -
A和他的parent 都必须是QObject, 那么A(如果是用new 来分配的),就会在parent被释放的时候释放。

Q2我还是不清楚, 当A被释放的时候,他里面用new 分配的不在QObject tree上的int  *a 应该在什么时候释放? 因为, 类A没有destructor, 因该在哪里释放合适?

coredump再讲详细点吧,谢谢阿。
作者: coredump    时间: 1-3-2009 00:23
标题: 回复 #94 GPS 的帖子
Q1:A能不能被正确释放要看怎么用,光看类声明/定义没用。
         比如:A* pA = new A();  这样的代码是不可能被自动释放的,因为它不属于任何一个对象树,或者说它是一个独立对象树的根,你要手工管理它的内存分配。 而A* pA = new A(parent); 这里parent是另一个QObject对象,则pA指向的对象属于parent对象树中的一个节点,被parent自动管理,parent释放时,pA指向的对象也自动释放,无需手工delete。

Q2:这是对C++基本概念理解有误,除非是另一种语言,否则A里面的数据成员a是永远不会被释放的。管理这里的a应该采用C++的RAII风格:在构造函数中申请资源,在析构函数中释放资源。 QT的对象管理和这个是完全不同的两回事。
作者: GPS    时间: 1-3-2009 01:19
谢谢coredump,Q1已经清楚了。
Q2的话,是不是我要在类A中加个~A(){ delete []a;} ?
作者: migao21    时间: 1-3-2009 09:45
其实就是QT GUI类可以不用delete, 其他的new的都要delete, 所以Q2要写destructor里面的delete.
作者: GPS    时间: 1-3-2009 22:46
Thank you for all comments.

I understand as long as the QObjects are in the tree, they can be automatically released. If they are not in the tree, even if they are QObjects , they won't be released automatically.
作者: 四香油饼    时间: 2-3-2009 21:41
我这两天觉得还需要再学习学习,打好基础,正在看官方的那个qt编程指南,对于怎么用designer,还是比较晕阿
作者: 123ak    时间: 3-3-2009 21:42
QT念起来叫Qute. 希望我也能加入你们的学习小组。




欢迎光临 FreeOZ论坛 (https://www.freeoz.org/bbs/) Powered by Discuz! X3.2