本节,我们将在前面主窗口基础之上,添加菜单和工具栏等的动作。虽然 Qt Creator 已经帮我们实现了主窗口的框架代码,但是具体的功能,还是需要我们一行行添加。
Qt 使用QAction
类作为动作。顾名思义,这个类就是代表了窗口的一个“动作”,这个动作可能显示在菜单,作为一个菜单项,当用户点击该菜单项,对用户的点击做出响应;也可能在工具栏,作为一个工具栏按钮,用户点击这个按钮就可以执行相应的操作。有一点值得注意:无论是出现在菜单栏还是工具栏,用户选择之后,所执行的动作应该都是一样的。因此,Qt 并没有专门的菜单项类,只是使用一个QAction
类,抽象出公共的动作。当我们把QAction
对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。
QAction
包含了图标、菜单文字、快捷键、状态栏文字、浮动帮助等信息。当把一个QAction
对象添加到程序中时,Qt 自己选择使用哪个属性来显示,无需我们关心。同时,Qt 能够保证把QAction
对象添加到不同的菜单、工具栏时,显示内容是同步的。也就是说,如果我们在菜单中修改了QAction
的图标,那么在工具栏上面这个QAction
所对应的按钮的图标也会同步修改。
下面我们来看看如何在QMainWindow
中使用QAction
:
// !!! Qt 5 // ========== mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); private: void open(); QAction *openAction; }; #endif // MAINWINDOW_H // ========== mainwindow.cpp #include <QAction> #include <QMenuBar> #include <QMessageBox> #include <QStatusBar> #include <QToolBar> #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("Main Window")); openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this); openAction->setShortcuts(QKeySequence::Open); openAction->setStatusTip(tr("Open an existing file")); connect(openAction, &QAction::triggered, this, &MainWindow::open); QMenu *file = menuBar()->addMenu(tr("&File")); file->addAction(openAction); QToolBar *toolBar = addToolBar(tr("&File")); toolBar->addAction(openAction); statusBar() ; } MainWindow::~MainWindow() { } void MainWindow::open() { QMessageBox::information(this, tr("Information"), tr("Open")); }
上面的代码分别属于两个文件:mainwindow.h 和 mainwindow.cpp。为了让 MainWindow 运行起来,我们还需要修改 main() 函数如下:
int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow win; win.show(); return app.exec(); }
当我们编辑好文件,点击运行,可以看到MainWindow
的运行结果:
这是一个相对完整的程序。首先,我们在MainWindow
类中添加了一个私有函数open()
和一个私有变量openAction
。在 MainWindow 的构造函数中,第一行我们调用了setWindowTitle()
,设置主窗口的标题。注意我们的文本使用tr()
函数,这是一个用于 Qt 国际化的函数。在后续章节中我们可以看到,我们可以使用 Qt 提供的国际化工具,将tr()
函数的字符串提取出来,进行国际化。由于所需进行国际化的文本应该被大多数人认识,所以,tr()
函数里面一般会是英文文本。
然后,我们在堆上创建了openAction
对象。在QAction
构造函数,我们传入了一个图标、一个文本和 this 指针。我们将在后面的文章中解释 this 指针的含义。
图标我们使用了QIcon
,传入值是一个字符串,这个字符串对应于 Qt 资源文件中的一段路径。Qt 资源文件的后缀名是 qrc。如果我们使用 Qt Creator,我们可以在新建文件中看到 Qt 资源文件。Qt 资源文件其实是一个 XML 描述的文件,表示 Qt 应用程序所需要的各个资源。我们可以使用普通文本编辑器打开这个文件:
<RCC> <qresource prefix="/images"> <file alias="doc-open">document-open.png</file> </qresource> </RCC>
我们会在后面的章节中详细介绍 Qt 资源文件(注意,资源文件需要在 pro 文件中使用 RESOURCES 引入。)。这里只需要了解,QIcon
的参数,以 : 开始,意味着从资源文件中查找资源。:/images/doc-open
就是找到了这里的 document-open.png 这个文件。(我们使用的是 png 格式的图片,这是 Qt 内置支持的图片格式。其他格式的图片,比如 jpg、gif 则需要插件支持。这些插件实际已经随着 Qt 一同发布。)
QAction
第二个参数中,文本值前面有一个 &,意味着这将成为一个快捷键。注意看截图中 File 的 F 有一个下划线。
下面一句,我们使用了setShortcut()
函数,用于说明这个QAction
的快捷键。Qt 的QKeySequence
为我们定义了很多内置的快捷键,比如我们使用的 Open。你可以通过查阅 API 文档获得所有的快捷键列表。 这个与我们自己定义的有什么区别呢?简单来说,我们完全可以自己定义一个tr("Ctrl+O")
来实现快捷键。原因在于,这是 Qt 跨平台性的体现。比如 PC 键盘和 Mac 键盘是不一样的,一些键在 PC 键盘上有,而 Mac 键盘上可能并不存在,或者反之。使用QKeySequence
类来添加快捷键,会根据平台的不同来定义相应的快捷键。
setStatusTip()
则实现了当用户鼠标滑过这个 action 时,会在主窗口下方的状态栏显示相应的提示。
后面的connect()
函数,将这个QAction
的triggered()
信号与MainWindow
类的open()
函数连接起来。当用户点击了这个QAction
时,会自动触发MainWindow
的open()
函数。这是我们之前已经了解过的。
下面的menuBar()
、toolBar()
和statusBar()
三个是QMainWindow
的函数,用于创建并返回菜单栏、工具栏和状态栏。我们可以从代码清楚地看出,我们向菜单栏添加了一个 File 菜单,并且把这个QAction
对象添加到这个菜单;同时新增加了一个 File 工具栏,也把QAction
对象添加到了这个工具栏。我们可以看到,在菜单中,这个对象被显示成一个菜单项,在工具栏变成了一个按钮。至于状态栏,则是出现在窗口最下方,用于显示动作对象的提示信息的。
至于open()
函数中的内容,我们会在后文介绍。这里可以运行一下,你会看到,触发这个动作,程序会弹出一个提示框。
下面是 Qt 4 版本的程序,具体非常类似,这里不再赘述。
// !!! Qt 4 // ========== mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void open(); private: QAction *openAction; }; #endif // MAINWINDOW_H // ========== mainwindow.cpp #include <QAction> #include <QMenuBar> #include <QMessageBox> #include <QToolBar> #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("Main Window")); openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this); openAction->setShortcuts(QKeySequence::Open); openAction->setStatusTip(tr("Open an existing file")); connect(openAction, SIGNAL(triggered()), this, SLOT(open())); QMenu *file = menuBar()->addMenu(tr("&File")); file->addAction(openAction); QToolBar *toolBar = addToolBar(tr("&File")); toolBar->addAction(openAction); statusBar(); } MainWindow::~MainWindow() { } void MainWindow::open() { QMessageBox::information(this, tr("Information"), tr("Open")); }
196 评论
请问这行什么来头……没有读懂……
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
这是 C++ 的继承的语法的一部分,说明 MainWindow 的构造函数之前需要调用父类 QMainWindow 的带有参数的构造函数。类似于 Java 的 super()。
多谢,看来对语言特性学习不够,不好意思。
请问为什么我按这个代码会显示非法试用“void”类型呢?用的是QT5
你好 请问 我注释调QMainWindow(parent)貌似也没有什么影响 不用这句可以吗?
这里是调用了父类的构造函数。一般而言,子类应该调用父类的同参数构造函数,以便正确构造父类。在这里并没有什么太大的影响,但是再其它应用场景,如果你没有调用,可以认为编译器会调用 QMainWindow(0) 构造函数,这样的话,parent 指针就不能传递给父类,可能会造成奇怪的错误。因此建议添加这一语句。
请问一下为什么我把代码运行的结果中没有那个小图片呢
QIcon(":/images/doc-open.png"),感觉这一个没有加载出相应的图片,为什么呢?
鼠标移到 那个地方后是个空白的矩形框
有可能是图像路径的问题。检查过路径之后尝试重新运行 qmake 再编译,看看有没有解决。
路径问题,请参考:http://zhidao.baidu.com/link?url=3NI7a72u1HkFqKeBz3ZsC--U9j4PuMSIRfmcNN8tOs1AJy2ibGS450yfX658zZKz1wl_aCcquy7sJmdQghLtiguWvlArxUIWDJjy_d642pi
路径问题,请参考:
http://zhidao.baidu.com/link?url=3NI7a72u1HkFqKeBz3ZsC--U9j4PuMSIRfmcNN8tOs1AJy2ibGS450yfX658zZKz1wl_aCcquy7sJmdQghLtiguWvlArxUIWDJjy_d642pi
把图片添加到qrc中就好了:add new--Qt--Qt Resource File,打开.qrc文件,add--add prefix--add file,把图片加进去。
在菜单栏添加QAction之后,添加图标,怎么设置按下菜单栏之后,“按钮”变灰
connect(openAction, &QAction::triggered, this, MainWindow::open);
MainWindow::open 前面应该要加上 & 符号吧。
是的,感谢指出
QMenu *file = menuBar()->addMenu(tr("&File"));
请问关于这里的menuBar是来处于哪里呀?
哦,漏看了, menuBar是QMainWindow的.
是的。menuBar() 是 QMainWindows 的一个函数。
楼主是不是少了一段关于状态栏的代码:
QStatusBar *statBar = statusBar() ;
statBar->addAction(openAction);
setStatusBar(statBar);
不然openAction->setStatusTip(tr("Open an existing file"));这句话的意义体现不出来的
已经添加上了这段代码,感谢提醒哦~
QStatusBar *statBar = statusBar() ;
上面这行代码貌似有错误:
error C2064: term does not evaluate to a function taking 0 arguments
这个错误可能是因为函数与变量同名了。在某些编译器的某些版本中,函数名不能与变量同名,所以尝试使用 QStatusBar *statBar = statusBar(); 这种(PS: 文中代码中没有 statBar 这个名字)。
好吧,果然是我弄晕了。
这样子:
QStatusBar *statBar = statusBar() ;
statBar->addAction(openAction);
就行了。多谢回复!
我也出现了同样的问题,看了这个评论修正了
LZ,我发现用QT5编译的话最后的statusbar那几句都不用添加,只要openAction里有setstatus了就可以实现鼠标hover到的时候statusbar就有信息的功能,是不是QT5新的修改?
tomisacat的说法没错,不用添加。
同样问题,Qt 5.5.1 不需要添加这段代码。
这段代码在哪里呀,没有这段代码呀?
openAction是在MainWindow构造函数里面申请的堆内存,是不是应该在析构函数里释放?
file、toolbar这些应该也是堆内存吧?需要释放吗?
Qt 就是 C++,因此 C++ 的要求也适用于 Qt。C++ 要求堆上面创建的对象必须释放,Qt 当然也是。只不过注意下,这里我们传入了 this 指针作为 parent(详细参数列表参考文档),当存在 parent 指针时(也就是这里的情况),Qt 保证,在 parent 析构时,所有子元素全部析构。由于我们的 MainWindow 是建立在栈上的,当 main() 函数退出时,MainWindow 会被自动析构,此时,所有以其为 parent 的对象全部自动析构。所以我们不需要自己去写 delete 语句,并且也不能写!因为如果我们添加了 delete,Qt 在析构 MainWIndow 时又会再次 delete 同一对象,造成程序崩溃。
我测试了一下,在~MainWindow中,delete 了openAction ,但是程序没有崩溃
因为在析构函数中直接 delete 子对象,会将其从 children 列表中移除,不会照成 delete 两次的情况。
file、toolbar为栈内存
楼主好,有个问题想问你,在你的代码中有这么一句话:
openAction = new QAction(QIcon("./images/myicon"), tr("&Open..."), this);
我的电脑是win8,试了,不行,但是我改成
openAction = new QAction(QIcon("./images/myicon"), tr("&Open..."), this);
这是因为Os不同的原因吗?相对路径不是用 .的方法来表示吗?
还有,如果用
openAction= new QAction(QIcon("image/icon"),tr("&open..."),this);
也是可以的。
抱歉,今天在复习,进度没赶上,加油,支持楼主!
好吧。我懂了,我用资源文件的方式在做了次,可以。
但是我现在有2个问题,麻烦解答
Q1.为什么我在资源文件中写
image/icon.ico
编译有错,说是RCC: Error in '..\QACTION\image.qrc': Cannot find file 'image/icon.ico'
但是我看了别人网上的文章,别人是这么写的
images/copy.png
images/paste.png
为什么我不可以?
Q2.为什么我最后形成效果和你的截图不一样,我的快捷键的没有下划线?
好吧,上传不了图片,无图无真相...
A1. 第一个资源文件没找到,可能是路径问题,或者是文件格式,你可以换成 png 试试看看行不行。如果 png 可以,就说明是 Qt 的 ico 插件没有加载。对于 png 文件,Qt 是内置的,ico 需要使用插件完成。
A2. 如果你是 Windows 7,需要按下 Alt 键才会显示下划线,这是操作系统决定的,不同的系统具有不同的行为,这点不可能统一的。
为什么如果我这样写会提示错误,
QStatusBar *statusBar = statusBar() ;
statusBar->addAction(openAction);
错误:'statusBar' cannot be used as a function
然而把statusBar换个其他的名字就没事了呢?
我的是unbuntu 64位
这个错误之前也遇到过,貌似有的编译器不允许局部变量同函数重名。C++ 只是规定,不允许成员变量与函数同名,某些编译器可能将其限制到,不允许任何变量与函数同名。这可能是编译器的一个 bug。具体也不大清楚 ;-P
还有楼上有一个人说的
加上这个:
setStatusBar(statBar);
这个语句有什么用呢?
您说您修改了,可是我看您代码里并没有这句话啊。
应该就是下面两句:
QStatusBar *statusBar = statusBar();
setStatusBar() 用于将自己的状态栏设置为窗口状态栏,但是在这里并不适用。因为这里获取的 QStatusBar * 实际从窗口而来,因此并不需哟啊再设置一次。当然,由于这是同一个对象,即便调用 setStatusBar() 也没有任何问题,只不过是多余的。
能不能推荐一本中文版讲解QT5.0的书呢?现在世面上都是4的。您的教程讲的很好,但好多地方讲的不够细致,想找本书研究一下。
我和你一样也是ubuntu,估计gcc不允许同名吧。只能改名。。。
maneBar()写错了,应该是menuBar吧
多谢指出,已经修改过了!
为什么我的程序中的文字总是没有下划线 "&File"这样的,在程序里F没有下划线
如果你的系统是 Windows 7,默认是不显示下划线的,需要你按下 Alt 键之后才会显示。这是操作系统决定的,你可以看一下其它程序也是类似的行为。
请问
statusBar->addAction(openAction);
这行代码是干嘛用的?查文档知道 addAction 是基类 QWidget 的函数,用于将动作添加至 widget 的动作列表。可是我不明白这个函数对 QStatusBar 有何意义?如果是为了当鼠标放在工具栏按钮上产生提示信息,那openAction->setStatusTip(tr("Open an existing file"));
这句不是已经实现了吗?我试过,注释掉addAction那行代码,程序行为似乎没受到影响。这行代码应该是没有作用的,已经从示例中去除。感谢提醒!
icon.png
这是我的资源文件,openAction = new QAction(QIcon(":/images/open"), tr("&Open..."), this); 我的系统是win7,qt5,为什么我的图标一直不能显示,是一个空白的方块,我的资源文件用资源管理器打开,都能显示出图标,希望能找到原因,谢谢。
不清楚你说的“资源管理器打开”是 IDE 里面的吗?显示空白可能是因为路径问题,也可能是因为发布的时候找不到对应的插件
今天試過也發現這個問題
發現需要再次qmake才行
僅供參考
如果是后来新增加的 qrc 文件,很可能是因为之前 qmake 生成的 makefile 没有包含这个文件,所以要重新运行 qmake 重新生成 makefile
qresource prefix="/images"
file alias="open" icon.png file
qresource
貌似过滤一些字符,所以我把尖括号删了,补发一下。
是不是需要在setWindowTitle前面加一句,ui->setupUi(this);
ui->setupUi(this); 是在你使用了 UI 文件的时候需要添加的,意思是要把你创建的 UI 设计文件与这个类关联起来,如果没有使用 Qt Designer 设计的话就不需要了。
确实是这样,thx楼主回复,还有一个小问题就是document-open.png这个图片文件要放在cpp所在文件夹么?我这也是空白 , win7下
图片文件不一定放在 cpp 目录下,只要路径正确就可以读到
那个第一段代码里面的statusBar->addAction(openAction);还是木有加上。 😛
另外,博主在上头说statusBar报错是编译器的问题,感觉不是啊,正常的编译器应该都会报这个错误的(在C语言中也是这样的),声明statusBar的那前半句在作用空间会屏蔽其他名字是statusBar的函数,所以在调用statusBar()的时候报错。不过我也没看过标准上是怎么说的,测试了一下,gcc和clang都报错了。
应该没有 statusBar->addAction(openAction); 这句的,只需要一个 statusBar() 函数即可。至于名字的问题,我也没有在标准上看到。为了避免类似的问题,还是不要写一样的名字了
豆子老师,在声明过程中我对QMessageBox 使用了向前声明于是产生了这个错误
错误:incomplete type 'QMessageBox' used in nested name specifier
然后改为头文件包含于是正确编译。
但是 我对QAction 向前声明却可以正确编译。
这是怎么回事?还有我最近遇到好多问题都与向前声明有关,只有改为包含头文件才能正确编译,上面只是其中一例,
我的操作环境:
os: windows 7 x64
qt 版本: 4.8
编译器:MinGW 4.4.0/bin
调试器:gdb-7.4-MINGW32_NT-6.1-i686
前向声明是 C++ 语言提供的改善编译时间的一种机制,并不用于取代 include。简单来说,如果你的代码需要“使用”类,也就是调用了类的函数、成员之类,就必须使用 include(头文件中不以指针方式声明成员变量,都是隐含调用了构造函数,也相当于使用类);反之,如果仅仅告诉编译器“有”这么个类,并不“使用”它,比如以指针声明类,则只需要使用前向声明。也就是说,在 cpp 文件中,前向声明基本没有意义(因为不大可能不在 cpp 文件中使用类,并且在 cpp 文件中使用前向声明一般不会减少编译时间,而是更多地用于头文件中)。如果不清楚,请自行阅读 C++ 基础教程。
一个月前才开始学习c++,基础薄弱。
感谢豆子老师指出来。 🙂
/images/doc-open 这个图标文件是要自己准备好吗?还是调用的qt自带的图标
不是 Qt 自带的,需要你自己准备好
豆子老师,我有一个问题想不明白,为什么在Qt里,图标是由QAction负责设定的,而不是由QMenu负责指定。也就是说,我需要在创建QAction的时候制定图标,而在QMenu上直接调用addAction添加相应的QAction。为什么不设计成在创建QMenu对象的时候制定这个Menu对象的图标属性,而QAction对象只负责发送动作产生的信号?
这个只是 Qt 的设计思路,像你的那种设计思路也是可行的。不过总体来说,同一个 action 的图标一般是不会变化的,对于那种同一个 action,在 menu 和 toolbar 的图标不一致的情况几乎不存在,所以图标一般会直接作为 action 的一个属性。否则的话,你需要给 menu 设置图标,然后再给 toolbar 设置图标。
感谢!
只是本人基础薄,大部分类、对象的关系不清楚,有没有像MSDN一样的帮助可以查啊,具体指点迷津,不胜感激!!
Qt Creator 中的帮助不亚于 MSDN 的详细程度,只是 Qt 文档一直没有类似的 UML 类图。如果想看类图只能自己做反向工程了
编译无法通过:
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
错误提示:
mainwindow.cpp:18: 错误:C2227: “->addMenu”的左边必须指向类/结构/联合/泛型类型。
我的系统 win7 使用 QT5.1.1, Creator 2.8.1
查了很多资料,都没有找到原因,敬请博主给予帮助。
解决了:
忘记包含 QMenuBar 头文件了。
照着抄了一遍,这句QMessageBox::information(this, tr("Information"), tr("Open"));坑爹了。
原因是Qt Creator 自动补全将infomation 的第一个字母大写了.
第一个字母大写的是 Icon 枚举,Qt Creator 自动补全成枚举值了
楼主你好,我是WIN7 64位 QT5 下做的, 按你的代码抄了下,可是connect(action, &QAction::triggered, this, &MainWindow::open);这句老是过不了。
mainwindow.obj:-1: error: LNK2019: 无法解析的外部符号 "public: void __cdecl MainWindow::open(void)" (?open@MainWindow@@QEAAXXZ),该符号在函数 "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow@@QEAA@PEAVQWidget@@@Z) 中被引用
楼主你好,我按照 你的代码自己写了一下,可是 connect(action, &QAction::triggered, this, &MainWindow::open);老是报错。mainwindow.obj:-1: error: LNK2019: 无法解析的外部符号 "public: void __cdecl MainWindow::open(void)" (?open@MainWindow@@QEAAXXZ),该符号在函数 "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow@@QEAA@PEAVQWidget@@@Z) 中被引用
WIN7 64 QT5.2
不好意思 ,是我忘了实现 OPEN方法。
博主,我想问下,openAction没有在析构函数中删除,会不会造成内存泄露?
使用menuBar()和statusBar()得到的对象是不是会自动析构?
openAction 不会造成内存泄露,因为 openAction 指定了 parent(就是 this 指针)。按照 QObject 的析构顺序,当一个 QObject 析构时,它会自动删除所有以自己为 parent 的对象。所以,openAction 的 parent 为 MainWindow,当 MainWindow 析构时,会自动将 openAction 析构。这一点在第10篇《对象模型》中有详细阐述。
至于 menuBar() 和 statusBar(),应该也是类似的情况。
啊,谢谢博主,已经看到了
F:\qttext\untitled\mainwindow.cpp:36: error: no matching function for call to 'MainWindow::tr(const char [12], QString)'
QMessageBox::information(this,tr("Information",tr("Open"));
请问博主,照着你qt5的代码抄下来了,可是却重复出现上面这个错误提示。查阅相关评论看到上面的咚冬博友提到,“Qt Creator 自动补全将infomation 的第一个字母大写了“,不知是不是这个原因。要怎么解决呢? ^
你的函数少了半个括号,QMessageBox::information(this,tr(“Information”),tr(“Open”)); 而不是 QMessageBox::information(this,tr(“Information”,tr(“Open”));,所以编译器的错误是 tr() 函数写错了,而不是 information() 的问题。
谢谢博主耐心解答。(豪弱智的错误。。。。)
按照信号槽那一章节的讲解,第三种形式
QMetaObject::Connection connect(const QObject *, const char *,
const char *,
Qt::ConnectionType) const;
“这个函数其实是将 this 指针作为 receiver”,于是我尝试将本文中代码修改为:
connect(openAct, &QAction::triggered, &MainWindow::open);
但是为什么编译不能通过?谢谢!
简单来说,Qt5 没有提供类似的函数,所以编译不能通过。Qt 5的 connect 新语法的参数类似有 PointerToMemberFunction 和 Functor,前者是成员函数指针,后者是一个不依赖于对象的函数指针(比如 static 函数、全局函数、Lambda 表达式等)。Qt 5 提供的 3 个参数的函数是:connect(const QObject * sender, PointerToMemberFunction signal, Functor functor),也就是说,Qt 5 支持将信号与一个不依赖于对象的函数连接起来。针对上面的例子,如果 open 是一个 static 函数,就可以通过了。
楼主,你好,我是mac系统,为啥死活不出来菜单栏呢,完全按你的代码抄的,窗口可见,那个open的图标看不到,菜单也看不到。。谢谢!
不好意思,是我搞错了,菜单有,但不是像windows那样,在Main title下面。。用mac时间不长。不好意思!
是的,这是 Mac 的风格,所有 Mac 程序都是这样的(如果不是这样,说明这个程序太不专业了)。
多谢,断断续续学QT很长时间了,总是各种各样的细节问题,只有贵宝地才这么系统,细节非常完善,博主可以考虑出书
请问这种情况是什么原因呢?谢谢 错误:invalid use of 'this' in non-member function
很有可能你的函数没有添加类名限定变成全局函数了,或者写成了 static 函数。这两种函数都不可以使用 this 指针的。
豆子,我用的是VS2008的环境,不是Qt Creator,我想请问下有没有像VS类似的Qt4小助手呢?还有我用VS2008的环境学习Qt4,按照您的这个文章思路来学习,有没有什么差异呢?谢谢豆子
差异不是很大。安装过 VS 插件之后开发起来还是比较方便的。VS 的话帮助文档就要另外打开了,一般安装过 Qt 后开始菜单里面都有的。
豆子老师,我运行出来的图标是空白的,代码中“/images/doc-open ”这个图标文件是自己准备好的,那么又放入什么地方呢?怎么样才能显示出您运行出来的效果呢?期待您上面那个问题和这个问题的解答,非常谢谢!
如果使用 qrc 文件,在创建之后可以将图标路径添加到 qrc 中。这个一般 IDE 都有支持。qrc 文件格式前面也有示例。添加过 qrc 之后,需要在 pro 文件中添加 RC_FILES 一行。如果不使用 qrc 文件,只要写相对于 exe 文件的相对路径即可。
谢谢豆子老师,已经弄好了,显示出来了~
豆子老师你好 我想问一下:images/doc-open 的这个images是会在本地建立这个文件夹吗
还是仅仅在项目中
还有我的图标不可以显示 显示图标的位置是可以点击的 应该是没加载进去
该如何去修改
不会的,使用图片文件需要事先放在某个文件夹下,才能够添加到 qrc 文件中。如果你的图标不显示,有可能是因为 qrc 文件没有编译,确定路径没有错误时,可以运行一下 qmake 或者执行重新编译试试。
豆子你好!
为什么我把他人(“&Open...”)的&符号删掉,运行后,还是可以用ctrl+O快捷键?
修改如下:
openAction = new QAction(QIcon(":/images/IFile"), tr("Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
&Open 的快捷键是 Alt+O,Ctrl+O 是因为 setShortcuts() 函数。
豆子老师,您好
我在学习你这个课程的时候,代码都一样,运行的时候在我的qt 5.3.1上总是提示:menuBar和statusBar的访问不明确,找不到标识符。其他的都没有问题。
请问是怎么回事?
谢谢!
看看父类是不是
QMainWindow
?这两个函数都是QMainWindow
的函数。另外看看有没有include
头文件。谢谢回复,我看过了,都没有问题啊,是MainWindow,头文件也包含了;
代码如下:
#include
#include
#include
#include
#include
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setWindowTitle(tr("Main Window"));
openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, &QAction::triggered, this, &MainWindow::open);
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
statusBar() ;
}
MainWindow::~MainWindow()
{
}
void MainWindow::open()
{
QMessageBox::information(this, tr("Information"), tr("Open"));
}
include上面的没有显示全,这里补充
#include
#include
#include
#include
#include
#include "mainwindow.h"
这个不清楚是怎么回事。你可以把完整代码发送到邮箱看看:devbean#outlook.com
好的,实在是太感谢了。
显示不全应该是被防 XSS 的插件过滤了吧……
豆子老师,你好,我初学Qt,,我在一个菜单下添加了多个项,几个图标,为什么有的图标就可以显示,有的就不行,在资源管理器中也看不了这些图片。谢谢
有可能是图标格式问题,或者路径问题。这个因为没有代码,所以不好分析究竟是什么问题
谢谢你的指导。但是在运行后看不到工具栏。
我使用的是QT 5.5 在win7 64bit 上运行。
请问这是什么原因?
QMessageBox::information(this,tr("Information"),tr("Open"));这段好像没什么用,点击没有弹出对话框
点击按钮之后应该是会弹出对话框的。如果没有的话,可能是哪里有问题了
请问对于程序要用的 #include 文件 是放在.cpp还是.h里 有什么要求吗 还是 都可以
一般会要求头文件越精简越好,所以,头文件一般 include 必须的,其它都用前置声明。大部分都会在 cpp 文件中。
你好!前面的文章里不是说slot函数不能设为private吗?要设为public或者protect?
slot 函数是可以作为 private 的;signal 作为宏,会被展开为 public 或者 protected。
有一点疑问。
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
file和toolBar这两个变量是在构造函数内部被定义和赋值的,那岂不是出了构造函数,他们就应该被销毁。
这里并不能得出这个结论。注意,如果不看源代码,你不能推断出,addMenu() 和 addToolBar() 这两个函数是如何实现的:是在堆上,还是在栈上分配内存空间,你所知道的仅仅是这两个函数返回了一个指针。如果是在栈上,它们必定会在超出作用域被销毁;如果是堆上则不会。(当然,从你所举的例子看,肯定是在堆上分配空间的,否则就像你所说的,一旦出了构造函数就会被销毁)
豆子老师您好,setShortcuts设置快捷键只需要设置这一个就行了吗?还是需要设置别的什么吗,为啥我设置了之后快捷键不好使。
不需要设置别的,不知道为什么不好用的?一般都是正常的
您好,我使用了原代码,但是菜单栏显示有问题,toolbar的按钮可以显示出来, 但是File无法显示,不知道是什么问题
File 显示不出来是什么样子的?菜单栏有没有正常显示?
豆子老师您好,我也遇到了这个问题.工具栏按钮可以显示,但是菜单栏File并没有显示.我试过先后注释掉菜单栏和工具栏,在这个过程中,感觉菜单栏的添加函数好像没有执行似的.
豆子你好,我用的是你的代码,也遇到了图标无法显示的问题以及File下面没有出现下划线。请问怎么确定“路径没错”?
Windows 平台,默认应该是按住 Alt 键才会显示下划线。没有图标,可以试着重新运行 qmake,然后重新构建整个项目,一般可以解决;如果还是没有,需要仔细检查路径是不是正确:qrc 文件中设置的前缀和路径是不是匹配这个图片
我单独创建MainWindow时,程序会生成一个默认的toolbar。运行上面的代码就会生成两个toobar。为什么例子中的图片只有一个toolbar。我应该怎么删除原来那个默认的toolbar?
如果是代码创建的话是不会自动添加一个工具栏的,注意看有没有界面文件(.ui 文件),.ui 文件会默认添加一个工具栏。你可以在设计模式将这个工具栏删掉,或者不使用界面文件。
请问如果我项目的时候选择的是QWidget,那要怎样创建菜单栏、工具栏和状态栏
QWidget 同样可以使用这些组件,不过需要自己利用布局添加,而 QMainWidow 实际可以看做是添加了布局的 QWidget。
请教一下,使用qt creator,qmake后能够显示图标,那使用VS2010编译,怎么才能显示图标?
问题解决了,就不麻烦您了
您好,QAction的setShortcut和setShortcuts有什么不同呢?查了下,两个函数的形参不太一样;试了试在这个例程中两个函数貌似没区别
setShortcut() 是设置一个快捷键;setShortcuts() 是设置一组快捷键。
请教下,我创建出来的 action问什么图片显示不了,png格式的,
openAction=new QAction(QIcon(":/images/open"),tr("&open.."),this)
目录没有错误,并且是通过添加资源文件形式添加进去的。
已经解决,是前缀错误导致
博主的文章很棒,评论区中也能找到许多有用的帮助。(又:网页设计很美观,哈哈)
tr("&Open...")中,Open...3个点什么意思
这是一种界面的习惯:如果一个菜单项点击之后会弹出对话框,一般会有 ... 后缀
你好,非常感谢你的教程,我使用的是Qt5.6,Qtcreator4.0.2,我尝试了下图片,并不支持png,但支持jpg格式的图片,图片加载,对于我们这种刚接触Qt的新手来说,并不是一件容易的事情,尤其是在不知道不支持png格式图片的情况下,我尝试了各种相对路径和绝对路径等方法,建议在文中说明,并附上资源文件加载的参考链接,我参考的是以下这个教程 http://www.cnblogs.com/cszlg/p/3234786.html
尴尬,原来你下一篇就是写的就是资源文件,不过还是建议你在本教程中提到资源文件加载的事情,两篇教程应该是要同时使用的:)
编译没错,运行,功能正常,但是不会出现图标。检查了一遍找不到哪里错了,把图片格式换成jpg也是一样。
文件夹和文件排列如下:
images
--08.qrc
--open.png
08.pro
main.cpp
mainwindow.cpp
mainwindow.h
//08.pro
TEMPLATE = app
TARGET = 08
INCLUDEPATH += .
# Input
HEADERS += mainwindow.h
SOURCES += main.cpp mainwindow.cpp
RESOURCES += images/08.qrc
QT += widgets
//08.qrc
open.jpg
前一个回复的qrc内容错了
//08.qrc
open.png
奇怪,为什么qrc的文件内容拷贝在回复框中,只显示"open.png"?
豆子能把文件夹和文件的排列显示一下吗?存放图片的images文件夹和QtCreator资源文件中的前缀images是一回事吗?
我用QtCreator创建的项目,也是没法显示图标啊,奇了怪了。
已经找到原因了:QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
图片路径前面少了个冒号。
总结了一下这个问题,请豆子看下。
图标路径有两种表示方式:
0. 假设文件放置路径如下:
release
--09.exe
images
--open.png
09.pro
09.qrc
main.cpp
mainwindow.h
mainwindow.cpp
1.相对路径1
open_action = new QAction(QIcon(":/images/images/open"), tr("&Open..."), this);
第1个images是在qrc文件中添加的前缀,第2个images是与.cpp,.h文件并列的文件夹,专门用来存放图片。
如果这时打开qrc文件,内容类似以下:
//09.qrc
images/open.png
所以相对路径的表示方式为: :/前缀名/文件夹名/文件名 。 注意前面的那个:不可缺少!!!
2.相对路径2
open_action = new QAction(QIcon("../images/open"), tr("&Open..."), this);
这种方法不需要考虑qrc中的前缀名,因为exe所在的文件夹与images文件夹并列,所以用..表示exe所在文件夹的上一级文件夹,这个文件夹下包含images文件夹,images文件夹下有open.png图片
使用 qrc 与不使用 qrc 是完全不同的:前者会编译成二进制代码,直接内嵌到 exe 中;后者会在运行时加载图片。二者适用于不同的场合:前者运行效率更高,但是不能由用户提供并切换;后者可以由用户提供图片并切换显示,适合于用户自定义主题等。
豆子的意思是说如下第2种办法是不使用qrc?
open_action = new QAction(QIcon(“../images/open”), tr(“&Open…”), this);
是的,这样是运行时加载的(路径没有冒号)
总结得不错,我也这样进行了实验,`.`是同级目录,`..`是上一级。
其实主要是觉得豆兄把prefix取名为images, `/images`很容易让人联想到这就是一个目录名或者图片的前缀都应该是images。
在此纠结很久,好歹试出来了。
接下来要跟这豆兄好好学
QMenu *file = menuBar()->addMenu(tr("&a"));
新手求教这句话能解释一下么 、menuBar指向addMenu是什么意思、可不可以像 QToolBar *toolBar = addToolBar(tr("&b"));这句话直接用addMenu?
menuBar() 是函数调用,返回一个 QMenuBar 对象的指针,然后再去调用这个对象的 addMenu() 函数。等价于:
这个是 C++ 的基础内容,可以先学习下 C++ 的相关知识。
QMenu *file=menuBar()->addMenu(tr(“&a”));与QMenu *file=menuBar()->addMenu(tr(“a”)); 有什么区别??
前面的 &a 会生成一个快捷键,Windows 平台下,按住 Alt 键会在 a 下面显示一个下划线;如果只是 a 的话就不会有这个快捷键。
好棒
您好,我在ubunu14.04系统下复制了上面内容,只有工具栏以及状态栏,没有显示菜单栏,也就是看不到“File”这个单词,想问问是什么原因?麻烦您了
我知道了,哎,ubuntu的菜单栏,在最上面,抱歉一直没看到
有一个问题不是很理解,“在堆上创建了openAction对象”,这个“堆”应该是与“栈”对应的,请问该如何理解
使用 new 关键字创建的对象,都是在堆上面分配空间;否则都是在栈上面分配的
这里 QAction *openAction,然后openAction = new QAction()
在QAction这个类的指针对象上新建一个实例(对象)QAction,第一个QAction是类名,第二个是函数名,这样理解对吗?
然后一个问题是,评论时是留下邮箱的,你回复了我的评论,并没有收到邮件反馈,有什么别的方法知道你给出了回复吗?
豆子老师,新手,为什么我把你的代码直接复制,mainwindow.h,mainwindow.cpp,main.cpp三个,运行了窗口却和之前一样,没有发生改变,没有菜单栏、工具栏等,我用的QT5.4.0,不知道哪里出问题了,麻烦您指教一下?
有没有重新构建下试试?或者重新运行 qmake 之后再 build
豆子大大,我的也是这个问题
有菜单栏但是没有工具栏。而且addMenu()函数要么只能显示出图标,要么只显示“File”,没办法实现
QMenu *QMenuBar::addMenu(const QIcon &icon, const QString &title)
请豆子大大多指教~
老师您好 我的QT creator 用起来十分的卡 编辑页面点击没有反应 所以我用VS2015加插件的方式创建QT项目 但是创建后的项目中好像没有 mainwindows.h 和 mainwindows.app 只有main.cpp 项目名.cpp 项目名.h等 请问像上面的”QMainWindow中使用QAction” 应该怎么实现呢 感谢老师回复
老师我知道了 这个是之前指定的类名 我默认是和项目名一样啦
另外就是QT creator 的卡顿问题应该怎么办呢 在编辑页面上所有操作是有效的但是都不是直接显示 需要切到别的页面比如欢迎页再切回来才会显示之前的变化
卡顿的问题不清楚是什么原因,估计要检查本机环境之类的了
为什么我会出现这个错误 D:\SW\QT\dongzuo\dongzuo\mywidget.cpp:21: error: 'menuBar' was not declared in this scope
QMenu *file = menuBar()->addMenu(tr("&File"));
^
D:\SW\QT\dongzuo\dongzuo\mywidget.cpp:24: error: 'addToolBar' was not declared in this scope
QToolBar *toolBar = addToolBar(tr("&File"));
^
addToolar() 是 QMainWindow 的函数,是不是你在调用的时候不是 QMainWindow?
运行时出现错误,调试时发现是在 mainwindow.cpp中的file->addAction(openAction);出错的,系统是macOS,Qt5.12.1
我尝试改成这样的语句就不会在运行时终止
QMenuBar *file = menuBar();
file->addMenu(tr("&File"));
file->addAction(openAction);
tr(“&File”)中加了个&,我去掉&后,程序也正常跑,请问一下这个&有什么意义么?一时没搞懂
& 会将后面的字符变成快捷键。在 Windows 平台按下 Alt 键,会显示一个下划线,作为快捷键的标记。
豆子,请问下 Separate Action的功能是什么呢?
打错啦~是Separator Action
我懂啦~谢谢
老师,您好,为什么我运行时出现了17: error: undefined reference to `MainWindow::open()'错误。版本是Qt Creator 4.2.1
请问QT自身的众多快捷键也是setShortcuts设置的吗?更改QT的快捷键时发生了什么?
豆子老师:
有个问题问下,
QMenuBar *qmenubar = new QMenuBar();
QMenuBar *qmenubar = menuBar();
这两种写法,有什么不同吗,第一种不能显示,第二种正常。
第一种是使用构造函数创建,第二种是调用了 QMainWindow 的函数返回。menuBar() 已经把 QMenuBar 添加到窗口,所以可以直接显示,而构造函数创建之后,你需要手动添加到窗口才行
多谢豆子老师
:-1: error: [ui_mainwindow.h] Error 127
请教出现了错误,资源文件路径没有发现问题 看过下一节的资源文件说明
已经解决了 谢谢
我也是找不到,谢谢你我也看到了!
作者大大,请问现在(2019年10月)这篇教程,会不会过时了,好像这个教程里没有用到设计师,是当时设计师还没用出吗?还是设计师没什么用。。。反正我用的qt4.3.0版本按照上面这个代码,在MainWindow类里面会出现一个UI对象
没有,只是因为个人偏好没有使用设计师。其实设计师对于界面的快速开发还是很有帮助的,不过鉴于这系列文章是教程性质,所以没有引入过多的内容。另外,因为感觉设计师生成的代码可读性有些不好,个人很少使用设计师,所以也没有涉及这部分内容。
你好,我是小白一枚!复制粘贴你的代码,linux下运行没有显示菜单栏,想请教一下这是为什么,也没有报错!谢谢!
linux 使用的什么桌面?QMenu 会按照具体的桌面去设置。如果你的桌面环境并没有每个窗口的菜单栏(类似 macOS),那么就会按照系统的显示来。窗口菜单栏可能被合并到桌面的公共菜单栏。
好的!谢谢!
确实合并到桌面的公共菜单栏了!
豆子哥,问一下!我在ubuntu16.04+qt5.7.1运行你的这篇代码,但是菜单栏没效果,工具栏和状态栏等其他都显示正常,这是为什么?谢谢!
您好,怎么重新运行qmake呢,我把图片路径改为绝对路径,点了绿三角编译运行后还是没出来,是需要重新qmake吗
点右键可以运行 qmake
您好,请问为什么创建项目的时候要是带了.ui文件,就显示不了菜单栏呢?
或者是因为什么别的原因
cpp里的最后这句statusBar();在QT5.14.1里可以去掉液没有影响。
补充一下:Qt新建项目的时候会在MainWindow的构造函数里自动添加ui->setupUi(this);这一句,如果菜单栏的相关代码在这一句之前,就会导致显示不出来菜单栏。把ui->setupUi(this)移到开头就行。
最新的 qt6 里,那个 menuBar 出不来了。。
有了 看错了。