首页 Qt 学习之路 2 Qt 学习之路 2(8):添加动作

Qt 学习之路 2(8):添加动作

196 14.9K

本节,我们将在前面主窗口基础之上,添加菜单和工具栏等的动作。虽然 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的运行结果:

Main Window with Action

这是一个相对完整的程序。首先,我们在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()函数,将这个QActiontriggered()信号与MainWindow类的open()函数连接起来。当用户点击了这个QAction时,会自动触发MainWindowopen()函数。这是我们之前已经了解过的。

下面的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 评论

Anonymous 2012年8月31日 - 01:26

请问这行什么来头……没有读懂……

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)

回复
DevBean 2012年8月31日 - 08:02

这是 C++ 的继承的语法的一部分,说明 MainWindow 的构造函数之前需要调用父类 QMainWindow 的带有参数的构造函数。类似于 Java 的 super()。

回复
Anonymous 2012年8月31日 - 10:41

多谢,看来对语言特性学习不够,不好意思。

回复
Junoja 2014年11月20日 - 14:33

请问为什么我按这个代码会显示非法试用“void”类型呢?用的是QT5

回复
zwb 2016年3月8日 - 09:55

你好 请问 我注释调QMainWindow(parent)貌似也没有什么影响 不用这句可以吗?

回复
豆子 2016年3月8日 - 10:16

这里是调用了父类的构造函数。一般而言,子类应该调用父类的同参数构造函数,以便正确构造父类。在这里并没有什么太大的影响,但是再其它应用场景,如果你没有调用,可以认为编译器会调用 QMainWindow(0) 构造函数,这样的话,parent 指针就不能传递给父类,可能会造成奇怪的错误。因此建议添加这一语句。

回复
Forward 2014年11月14日 - 12:55

请问一下为什么我把代码运行的结果中没有那个小图片呢
QIcon(":/images/doc-open.png"),感觉这一个没有加载出相应的图片,为什么呢?
鼠标移到 那个地方后是个空白的矩形框

回复
豆子 2014年11月18日 - 10:45

有可能是图像路径的问题。检查过路径之后尝试重新运行 qmake 再编译,看看有没有解决。

回复
sheldon zuo 2016年5月29日 - 19:49

路径问题,请参考:http://zhidao.baidu.com/link?url=3NI7a72u1HkFqKeBz3ZsC--U9j4PuMSIRfmcNN8tOs1AJy2ibGS450yfX658zZKz1wl_aCcquy7sJmdQghLtiguWvlArxUIWDJjy_d642pi

回复
we_qt5 2016年11月14日 - 12:54

把图片添加到qrc中就好了:add new--Qt--Qt Resource File,打开.qrc文件,add--add prefix--add file,把图片加进去。

回复
TingQT 2019年6月17日 - 14:42

在菜单栏添加QAction之后,添加图标,怎么设置按下菜单栏之后,“按钮”变灰

回复
羊八井 2012年10月7日 - 00:20

connect(openAction, &QAction::triggered, this, MainWindow::open);

MainWindow::open 前面应该要加上 & 符号吧。

回复
DevBean 2012年10月8日 - 08:14

是的,感谢指出

回复
esdf 2012年11月13日 - 06:25

QMenu *file = menuBar()->addMenu(tr("&File"));
请问关于这里的menuBar是来处于哪里呀?

回复
esdf 2012年11月13日 - 06:47

哦,漏看了, menuBar是QMainWindow的.

回复
DevBean 2012年11月13日 - 12:55

是的。menuBar() 是 QMainWindows 的一个函数。

回复
KOFLazycat 2012年11月14日 - 14:35

楼主是不是少了一段关于状态栏的代码:
QStatusBar *statBar = statusBar() ;
statBar->addAction(openAction);
setStatusBar(statBar);

不然openAction->setStatusTip(tr("Open an existing file"));这句话的意义体现不出来的

回复
DevBean 2012年11月14日 - 15:31

已经添加上了这段代码,感谢提醒哦~

回复
Rui-huai Zhang 2013年4月22日 - 22:05

QStatusBar *statBar = statusBar() ;
上面这行代码貌似有错误:
error C2064: term does not evaluate to a function taking 0 arguments

回复
豆子 2013年4月23日 - 09:05

这个错误可能是因为函数与变量同名了。在某些编译器的某些版本中,函数名不能与变量同名,所以尝试使用 QStatusBar *statBar = statusBar(); 这种(PS: 文中代码中没有 statBar 这个名字)。

回复
Rui-huai Zhang 2013年4月23日 - 15:58

好吧,果然是我弄晕了。
这样子:
QStatusBar *statBar = statusBar() ;
statBar->addAction(openAction);
就行了。多谢回复!

梓涵 2013年6月11日 - 11:22

我也出现了同样的问题,看了这个评论修正了

tomisacat 2013年8月12日 - 10:05

LZ,我发现用QT5编译的话最后的statusbar那几句都不用添加,只要openAction里有setstatus了就可以实现鼠标hover到的时候statusbar就有信息的功能,是不是QT5新的修改?

towardsocean 2015年6月13日 - 12:46

tomisacat的说法没错,不用添加。

Zaccur 2016年1月20日 - 13:13

同样问题,Qt 5.5.1 不需要添加这段代码。

HaborHuang 2014年1月2日 - 20:57

这段代码在哪里呀,没有这段代码呀?

回复
smile 2013年1月9日 - 15:56

openAction是在MainWindow构造函数里面申请的堆内存,是不是应该在析构函数里释放?
file、toolbar这些应该也是堆内存吧?需要释放吗?

回复
豆子 2013年1月9日 - 16:55

Qt 就是 C++,因此 C++ 的要求也适用于 Qt。C++ 要求堆上面创建的对象必须释放,Qt 当然也是。只不过注意下,这里我们传入了 this 指针作为 parent(详细参数列表参考文档),当存在 parent 指针时(也就是这里的情况),Qt 保证,在 parent 析构时,所有子元素全部析构。由于我们的 MainWindow 是建立在栈上的,当 main() 函数退出时,MainWindow 会被自动析构,此时,所有以其为 parent 的对象全部自动析构。所以我们不需要自己去写 delete 语句,并且也不能写!因为如果我们添加了 delete,Qt 在析构 MainWIndow 时又会再次 delete 同一对象,造成程序崩溃。

回复
sornor 2014年6月11日 - 09:51

我测试了一下,在~MainWindow中,delete 了openAction ,但是程序没有崩溃

回复
豆子 2014年6月12日 - 10:41

因为在析构函数中直接 delete 子对象,会将其从 children 列表中移除,不会照成 delete 两次的情况。

回复
瞬间 2016年8月26日 - 22:50

file、toolbar为栈内存

回复
hwb 2013年1月15日 - 21:05

楼主好,有个问题想问你,在你的代码中有这么一句话:
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);
也是可以的。

抱歉,今天在复习,进度没赶上,加油,支持楼主!

回复
hwb 2013年1月15日 - 22:53

好吧。我懂了,我用资源文件的方式在做了次,可以。
但是我现在有2个问题,麻烦解答
Q1.为什么我在资源文件中写

image/icon.ico

编译有错,说是RCC: Error in '..\QACTION\image.qrc': Cannot find file 'image/icon.ico'

但是我看了别人网上的文章,别人是这么写的

images/copy.png
images/paste.png

为什么我不可以?

Q2.为什么我最后形成效果和你的截图不一样,我的快捷键的没有下划线?

回复
hwb 2013年1月15日 - 23:00

好吧,上传不了图片,无图无真相...

回复
豆子 2013年1月16日 - 09:43

A1. 第一个资源文件没找到,可能是路径问题,或者是文件格式,你可以换成 png 试试看看行不行。如果 png 可以,就说明是 Qt 的 ico 插件没有加载。对于 png 文件,Qt 是内置的,ico 需要使用插件完成。

A2. 如果你是 Windows 7,需要按下 Alt 键才会显示下划线,这是操作系统决定的,不同的系统具有不同的行为,这点不可能统一的。

回复
JiaPan 2013年1月28日 - 15:11

为什么如果我这样写会提示错误,
QStatusBar *statusBar = statusBar() ;
statusBar->addAction(openAction);

错误:'statusBar' cannot be used as a function

然而把statusBar换个其他的名字就没事了呢?
我的是unbuntu 64位

回复
豆子 2013年1月28日 - 15:25

这个错误之前也遇到过,貌似有的编译器不允许局部变量同函数重名。C++ 只是规定,不允许成员变量与函数同名,某些编译器可能将其限制到,不允许任何变量与函数同名。这可能是编译器的一个 bug。具体也不大清楚 ;-P

回复
JiaPan 2013年1月28日 - 15:56

还有楼上有一个人说的
加上这个:

setStatusBar(statBar);

这个语句有什么用呢?
您说您修改了,可是我看您代码里并没有这句话啊。

回复
豆子 2013年1月28日 - 17:24

应该就是下面两句:

QStatusBar *statusBar = statusBar();

setStatusBar() 用于将自己的状态栏设置为窗口状态栏,但是在这里并不适用。因为这里获取的 QStatusBar * 实际从窗口而来,因此并不需哟啊再设置一次。当然,由于这是同一个对象,即便调用 setStatusBar() 也没有任何问题,只不过是多余的。

回复
JiaPan 2013年1月28日 - 19:47

能不能推荐一本中文版讲解QT5.0的书呢?现在世面上都是4的。您的教程讲的很好,但好多地方讲的不够细致,想找本书研究一下。

tttttbbb 2013年6月10日 - 19:44

我和你一样也是ubuntu,估计gcc不允许同名吧。只能改名。。。

回复
轨迹 2013年5月28日 - 13:26

maneBar()写错了,应该是menuBar吧

回复
豆子 2013年5月30日 - 10:52

多谢指出,已经修改过了!

回复
芽子 2013年7月5日 - 18:39

为什么我的程序中的文字总是没有下划线 "&File"这样的,在程序里F没有下划线

回复
豆子 2013年7月7日 - 12:48

如果你的系统是 Windows 7,默认是不显示下划线的,需要你按下 Alt 键之后才会显示。这是操作系统决定的,你可以看一下其它程序也是类似的行为。

回复
ghl 2013年7月16日 - 16:30

请问 statusBar->addAction(openAction);这行代码是干嘛用的?查文档知道 addAction 是基类 QWidget 的函数,用于将动作添加至 widget 的动作列表。可是我不明白这个函数对 QStatusBar 有何意义?如果是为了当鼠标放在工具栏按钮上产生提示信息,那 openAction->setStatusTip(tr("Open an existing file")); 这句不是已经实现了吗?我试过,注释掉addAction那行代码,程序行为似乎没受到影响。

回复
豆子 2013年7月17日 - 15:24

这行代码应该是没有作用的,已经从示例中去除。感谢提醒!

回复
kimihunhun 2013年7月24日 - 00:11

icon.png

这是我的资源文件,openAction = new QAction(QIcon(":/images/open"), tr("&Open..."), this); 我的系统是win7,qt5,为什么我的图标一直不能显示,是一个空白的方块,我的资源文件用资源管理器打开,都能显示出图标,希望能找到原因,谢谢。

回复
豆子 2013年7月24日 - 13:11

不清楚你说的“资源管理器打开”是 IDE 里面的吗?显示空白可能是因为路径问题,也可能是因为发布的时候找不到对应的插件

回复
Rice 2013年9月18日 - 12:51

今天試過也發現這個問題
發現需要再次qmake才行
僅供參考

回复
豆子 2013年9月18日 - 14:21

如果是后来新增加的 qrc 文件,很可能是因为之前 qmake 生成的 makefile 没有包含这个文件,所以要重新运行 qmake 重新生成 makefile

回复
kimihunhun 2013年7月24日 - 00:13

qresource prefix="/images"
file alias="open" icon.png file
qresource
貌似过滤一些字符,所以我把尖括号删了,补发一下。

回复
enockipp 2013年8月12日 - 23:41

是不是需要在setWindowTitle前面加一句,ui->setupUi(this);

回复
豆子 2013年8月13日 - 09:12

ui->setupUi(this); 是在你使用了 UI 文件的时候需要添加的,意思是要把你创建的 UI 设计文件与这个类关联起来,如果没有使用 Qt Designer 设计的话就不需要了。

回复
enockipp 2013年8月13日 - 10:18

确实是这样,thx楼主回复,还有一个小问题就是document-open.png这个图片文件要放在cpp所在文件夹么?我这也是空白 , win7下

回复
豆子 2013年8月13日 - 14:15

图片文件不一定放在 cpp 目录下,只要路径正确就可以读到

回复
漂木 2013年8月17日 - 16:17

那个第一段代码里面的statusBar->addAction(openAction);还是木有加上。 😛
另外,博主在上头说statusBar报错是编译器的问题,感觉不是啊,正常的编译器应该都会报这个错误的(在C语言中也是这样的),声明statusBar的那前半句在作用空间会屏蔽其他名字是statusBar的函数,所以在调用statusBar()的时候报错。不过我也没看过标准上是怎么说的,测试了一下,gcc和clang都报错了。

回复
豆子 2013年8月17日 - 21:16

应该没有 statusBar->addAction(openAction); 这句的,只需要一个 statusBar() 函数即可。至于名字的问题,我也没有在标准上看到。为了避免类似的问题,还是不要写一样的名字了

回复
tux 2013年8月26日 - 00:55

豆子老师,在声明过程中我对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

回复
豆子 2013年8月26日 - 09:06

前向声明是 C++ 语言提供的改善编译时间的一种机制,并不用于取代 include。简单来说,如果你的代码需要“使用”类,也就是调用了类的函数、成员之类,就必须使用 include(头文件中不以指针方式声明成员变量,都是隐含调用了构造函数,也相当于使用类);反之,如果仅仅告诉编译器“有”这么个类,并不“使用”它,比如以指针声明类,则只需要使用前向声明。也就是说,在 cpp 文件中,前向声明基本没有意义(因为不大可能不在 cpp 文件中使用类,并且在 cpp 文件中使用前向声明一般不会减少编译时间,而是更多地用于头文件中)。如果不清楚,请自行阅读 C++ 基础教程。

回复
tux 2013年8月26日 - 12:14

一个月前才开始学习c++,基础薄弱。
感谢豆子老师指出来。 🙂

回复
xyt 2013年9月17日 - 15:00

/images/doc-open 这个图标文件是要自己准备好吗?还是调用的qt自带的图标

回复
豆子 2013年9月18日 - 08:58

不是 Qt 自带的,需要你自己准备好

回复
devnull 2013年9月22日 - 13:22

豆子老师,我有一个问题想不明白,为什么在Qt里,图标是由QAction负责设定的,而不是由QMenu负责指定。也就是说,我需要在创建QAction的时候制定图标,而在QMenu上直接调用addAction添加相应的QAction。为什么不设计成在创建QMenu对象的时候制定这个Menu对象的图标属性,而QAction对象只负责发送动作产生的信号?

回复
豆子 2013年9月22日 - 20:07

这个只是 Qt 的设计思路,像你的那种设计思路也是可行的。不过总体来说,同一个 action 的图标一般是不会变化的,对于那种同一个 action,在 menu 和 toolbar 的图标不一致的情况几乎不存在,所以图标一般会直接作为 action 的一个属性。否则的话,你需要给 menu 设置图标,然后再给 toolbar 设置图标。

回复
qcp 2013年9月27日 - 22:53

感谢!
只是本人基础薄,大部分类、对象的关系不清楚,有没有像MSDN一样的帮助可以查啊,具体指点迷津,不胜感激!!

回复
豆子 2013年9月28日 - 15:12

Qt Creator 中的帮助不亚于 MSDN 的详细程度,只是 Qt 文档一直没有类似的 UML 类图。如果想看类图只能自己做反向工程了

回复
乔玉东 2013年11月5日 - 18:17

编译无法通过:
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
错误提示:
mainwindow.cpp:18: 错误:C2227: “->addMenu”的左边必须指向类/结构/联合/泛型类型。

我的系统 win7 使用 QT5.1.1, Creator 2.8.1

查了很多资料,都没有找到原因,敬请博主给予帮助。

回复
乔玉东 2013年11月5日 - 18:23

解决了:
忘记包含 QMenuBar 头文件了。

回复
咚冬 2013年11月14日 - 22:39

照着抄了一遍,这句QMessageBox::information(this, tr("Information"), tr("Open"));坑爹了。
原因是Qt Creator 自动补全将infomation 的第一个字母大写了.

回复
豆子 2013年11月15日 - 10:40

第一个字母大写的是 Icon 枚举,Qt Creator 自动补全成枚举值了

回复
陈胖子要逆袭 2013年12月20日 - 11:36

楼主你好,我是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) 中被引用

回复
陈胖子要逆袭 2013年12月20日 - 12:30

楼主你好,我按照 你的代码自己写了一下,可是 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

回复
陈胖子要逆袭 2013年12月20日 - 12:42

不好意思 ,是我忘了实现 OPEN方法。

回复
LSH 2014年1月2日 - 17:02

博主,我想问下,openAction没有在析构函数中删除,会不会造成内存泄露?
使用menuBar()和statusBar()得到的对象是不是会自动析构?

回复
豆子 2014年1月3日 - 11:34

openAction 不会造成内存泄露,因为 openAction 指定了 parent(就是 this 指针)。按照 QObject 的析构顺序,当一个 QObject 析构时,它会自动删除所有以自己为 parent 的对象。所以,openAction 的 parent 为 MainWindow,当 MainWindow 析构时,会自动将 openAction 析构。这一点在第10篇《对象模型》中有详细阐述。

至于 menuBar() 和 statusBar(),应该也是类似的情况。

回复
LSH 2014年1月3日 - 12:26

啊,谢谢博主,已经看到了

回复
gazzi 2014年2月17日 - 17:24

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 的第一个字母大写了“,不知是不是这个原因。要怎么解决呢? ^

回复
豆子 2014年2月17日 - 20:45

你的函数少了半个括号,QMessageBox::information(this,tr(“Information”),tr(“Open”)); 而不是 QMessageBox::information(this,tr(“Information”,tr(“Open”));,所以编译器的错误是 tr() 函数写错了,而不是 information() 的问题。

回复
gazzi 2014年2月18日 - 06:01

谢谢博主耐心解答。(豪弱智的错误。。。。)

回复
Jimmy 2014年2月19日 - 11:22

按照信号槽那一章节的讲解,第三种形式
QMetaObject::Connection connect(const QObject *, const char *,
const char *,
Qt::ConnectionType) const;
“这个函数其实是将 this 指针作为 receiver”,于是我尝试将本文中代码修改为:
connect(openAct, &QAction::triggered, &MainWindow::open);
但是为什么编译不能通过?谢谢!

回复
豆子 2014年2月19日 - 11:38

简单来说,Qt5 没有提供类似的函数,所以编译不能通过。Qt 5的 connect 新语法的参数类似有 PointerToMemberFunction 和 Functor,前者是成员函数指针,后者是一个不依赖于对象的函数指针(比如 static 函数、全局函数、Lambda 表达式等)。Qt 5 提供的 3 个参数的函数是:connect(const QObject * sender, PointerToMemberFunction signal, Functor functor),也就是说,Qt 5 支持将信号与一个不依赖于对象的函数连接起来。针对上面的例子,如果 open 是一个 static 函数,就可以通过了。

回复
Johnny 2014年4月3日 - 23:35

楼主,你好,我是mac系统,为啥死活不出来菜单栏呢,完全按你的代码抄的,窗口可见,那个open的图标看不到,菜单也看不到。。谢谢!

回复
Johnny 2014年4月4日 - 00:00

不好意思,是我搞错了,菜单有,但不是像windows那样,在Main title下面。。用mac时间不长。不好意思!

回复
豆子 2014年4月4日 - 08:51

是的,这是 Mac 的风格,所有 Mac 程序都是这样的(如果不是这样,说明这个程序太不专业了)。

回复
Johnny 2014年4月5日 - 13:53

多谢,断断续续学QT很长时间了,总是各种各样的细节问题,只有贵宝地才这么系统,细节非常完善,博主可以考虑出书

回复
Kab 2014年5月21日 - 22:04

请问这种情况是什么原因呢?谢谢 错误:invalid use of 'this' in non-member function

回复
豆子 2014年5月23日 - 15:11

很有可能你的函数没有添加类名限定变成全局函数了,或者写成了 static 函数。这两种函数都不可以使用 this 指针的。

回复
xuan120520 2014年5月27日 - 19:36

豆子,我用的是VS2008的环境,不是Qt Creator,我想请问下有没有像VS类似的Qt4小助手呢?还有我用VS2008的环境学习Qt4,按照您的这个文章思路来学习,有没有什么差异呢?谢谢豆子

回复
豆子 2014年5月30日 - 09:08

差异不是很大。安装过 VS 插件之后开发起来还是比较方便的。VS 的话帮助文档就要另外打开了,一般安装过 Qt 后开始菜单里面都有的。

回复
xuan120520 2014年5月27日 - 21:10

豆子老师,我运行出来的图标是空白的,代码中“/images/doc-open ”这个图标文件是自己准备好的,那么又放入什么地方呢?怎么样才能显示出您运行出来的效果呢?期待您上面那个问题和这个问题的解答,非常谢谢!

回复
豆子 2014年5月30日 - 09:16

如果使用 qrc 文件,在创建之后可以将图标路径添加到 qrc 中。这个一般 IDE 都有支持。qrc 文件格式前面也有示例。添加过 qrc 之后,需要在 pro 文件中添加 RC_FILES 一行。如果不使用 qrc 文件,只要写相对于 exe 文件的相对路径即可。

回复
xuan120520 2014年5月30日 - 17:01

谢谢豆子老师,已经弄好了,显示出来了~

回复
gzy0011 2014年6月12日 - 22:17

豆子老师你好 我想问一下:images/doc-open 的这个images是会在本地建立这个文件夹吗
还是仅仅在项目中
还有我的图标不可以显示 显示图标的位置是可以点击的 应该是没加载进去
该如何去修改

回复
豆子 2014年6月13日 - 08:56

不会的,使用图片文件需要事先放在某个文件夹下,才能够添加到 qrc 文件中。如果你的图标不显示,有可能是因为 qrc 文件没有编译,确定路径没有错误时,可以运行一下 qmake 或者执行重新编译试试。

回复
source 2014年7月31日 - 15:11

豆子你好!
为什么我把他人(“&Open...”)的&符号删掉,运行后,还是可以用ctrl+O快捷键?
修改如下:
openAction = new QAction(QIcon(":/images/IFile"), tr("Open..."), this);
openAction->setShortcuts(QKeySequence::Open);

回复
豆子 2014年7月31日 - 16:07

&Open 的快捷键是 Alt+O,Ctrl+O 是因为 setShortcuts() 函数。

回复
vx 2014年8月10日 - 13:18

豆子老师,您好
我在学习你这个课程的时候,代码都一样,运行的时候在我的qt 5.3.1上总是提示:menuBar和statusBar的访问不明确,找不到标识符。其他的都没有问题。
请问是怎么回事?
谢谢!

回复
豆子 2014年8月10日 - 13:55

看看父类是不是QMainWindow?这两个函数都是QMainWindow的函数。另外看看有没有include头文件。

回复
vx 2014年8月10日 - 20:14

谢谢回复,我看过了,都没有问题啊,是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"));
}

回复
vx 2014年8月10日 - 20:15

include上面的没有显示全,这里补充
#include
#include
#include
#include
#include
#include "mainwindow.h"

回复
豆子 2014年8月11日 - 10:33

这个不清楚是怎么回事。你可以把完整代码发送到邮箱看看:devbean#outlook.com

回复
vx 2014年8月11日 - 17:48

好的,实在是太感谢了。

Chia 2015年2月4日 - 21:44

显示不全应该是被防 XSS 的插件过滤了吧……

唯儿 2015年6月8日 - 09:33

豆子老师,你好,我初学Qt,,我在一个菜单下添加了多个项,几个图标,为什么有的图标就可以显示,有的就不行,在资源管理器中也看不了这些图片。谢谢

回复
豆子 2015年6月11日 - 09:31

有可能是图标格式问题,或者路径问题。这个因为没有代码,所以不好分析究竟是什么问题

回复
chenjings 2015年7月19日 - 16:52

谢谢你的指导。但是在运行后看不到工具栏。
我使用的是QT 5.5 在win7 64bit 上运行。
请问这是什么原因?

回复
Taget L 2015年7月21日 - 10:53

QMessageBox::information(this,tr("Information"),tr("Open"));这段好像没什么用,点击没有弹出对话框

回复
豆子 2015年7月21日 - 16:21

点击按钮之后应该是会弹出对话框的。如果没有的话,可能是哪里有问题了

回复
无名 2015年8月16日 - 18:54

请问对于程序要用的 #include 文件 是放在.cpp还是.h里 有什么要求吗 还是 都可以

回复
豆子 2015年8月17日 - 10:41

一般会要求头文件越精简越好,所以,头文件一般 include 必须的,其它都用前置声明。大部分都会在 cpp 文件中。

回复
poofee 2015年11月2日 - 20:10

你好!前面的文章里不是说slot函数不能设为private吗?要设为public或者protect?

回复
豆子 2015年11月4日 - 14:02

slot 函数是可以作为 private 的;signal 作为宏,会被展开为 public 或者 protected。

回复
poofee 2015年11月2日 - 20:41

有一点疑问。
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);

QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
file和toolBar这两个变量是在构造函数内部被定义和赋值的,那岂不是出了构造函数,他们就应该被销毁。

回复
豆子 2015年11月4日 - 14:01

这里并不能得出这个结论。注意,如果不看源代码,你不能推断出,addMenu() 和 addToolBar() 这两个函数是如何实现的:是在堆上,还是在栈上分配内存空间,你所知道的仅仅是这两个函数返回了一个指针。如果是在栈上,它们必定会在超出作用域被销毁;如果是堆上则不会。(当然,从你所举的例子看,肯定是在堆上分配空间的,否则就像你所说的,一旦出了构造函数就会被销毁)

回复
Yann 2015年11月5日 - 09:11

豆子老师您好,setShortcuts设置快捷键只需要设置这一个就行了吗?还是需要设置别的什么吗,为啥我设置了之后快捷键不好使。

回复
豆子 2015年11月5日 - 10:27

不需要设置别的,不知道为什么不好用的?一般都是正常的

回复
LouiseGAN 2015年11月10日 - 09:53

您好,我使用了原代码,但是菜单栏显示有问题,toolbar的按钮可以显示出来, 但是File无法显示,不知道是什么问题

回复
豆子 2015年11月13日 - 15:54

File 显示不出来是什么样子的?菜单栏有没有正常显示?

回复
jiangcheng 2016年3月29日 - 23:17

豆子老师您好,我也遇到了这个问题.工具栏按钮可以显示,但是菜单栏File并没有显示.我试过先后注释掉菜单栏和工具栏,在这个过程中,感觉菜单栏的添加函数好像没有执行似的.

回复
Tank93 2015年11月17日 - 16:21

豆子你好,我用的是你的代码,也遇到了图标无法显示的问题以及File下面没有出现下划线。请问怎么确定“路径没错”?

回复
豆子 2015年11月17日 - 23:18

Windows 平台,默认应该是按住 Alt 键才会显示下划线。没有图标,可以试着重新运行 qmake,然后重新构建整个项目,一般可以解决;如果还是没有,需要仔细检查路径是不是正确:qrc 文件中设置的前缀和路径是不是匹配这个图片

回复
Rainfd 2015年11月23日 - 10:47

我单独创建MainWindow时,程序会生成一个默认的toolbar。运行上面的代码就会生成两个toobar。为什么例子中的图片只有一个toolbar。我应该怎么删除原来那个默认的toolbar?

回复
豆子 2015年11月23日 - 17:43

如果是代码创建的话是不会自动添加一个工具栏的,注意看有没有界面文件(.ui 文件),.ui 文件会默认添加一个工具栏。你可以在设计模式将这个工具栏删掉,或者不使用界面文件。

回复
small 2015年12月12日 - 14:45

请问如果我项目的时候选择的是QWidget,那要怎样创建菜单栏、工具栏和状态栏

回复
豆子 2015年12月14日 - 21:55

QWidget 同样可以使用这些组件,不过需要自己利用布局添加,而 QMainWidow 实际可以看做是添加了布局的 QWidget。

回复
usopp 2015年12月25日 - 11:25

请教一下,使用qt creator,qmake后能够显示图标,那使用VS2010编译,怎么才能显示图标?

回复
usopp 2015年12月25日 - 13:11

问题解决了,就不麻烦您了

回复
fusuyang 2015年12月25日 - 21:53

您好,QAction的setShortcut和setShortcuts有什么不同呢?查了下,两个函数的形参不太一样;试了试在这个例程中两个函数貌似没区别

回复
豆子 2015年12月29日 - 15:57

setShortcut() 是设置一个快捷键;setShortcuts() 是设置一组快捷键。

回复
guoyinbo2012 2016年3月18日 - 10:14

请教下,我创建出来的 action问什么图片显示不了,png格式的,
openAction=new QAction(QIcon(":/images/open"),tr("&open.."),this)
目录没有错误,并且是通过添加资源文件形式添加进去的。

回复
guoyinbo2012 2016年3月18日 - 10:21

已经解决,是前缀错误导致

回复
Kempinski 2016年4月21日 - 20:11

博主的文章很棒,评论区中也能找到许多有用的帮助。(又:网页设计很美观,哈哈)

回复
sheldon zuo 2016年5月29日 - 19:47

tr("&Open...")中,Open...3个点什么意思

回复
豆子 2016年6月3日 - 12:37

这是一种界面的习惯:如果一个菜单项点击之后会弹出对话框,一般会有 ... 后缀

回复
卖鱼的小白菜 2016年7月3日 - 16:48

你好,非常感谢你的教程,我使用的是Qt5.6,Qtcreator4.0.2,我尝试了下图片,并不支持png,但支持jpg格式的图片,图片加载,对于我们这种刚接触Qt的新手来说,并不是一件容易的事情,尤其是在不知道不支持png格式图片的情况下,我尝试了各种相对路径和绝对路径等方法,建议在文中说明,并附上资源文件加载的参考链接,我参考的是以下这个教程 http://www.cnblogs.com/cszlg/p/3234786.html

回复
卖鱼的小白菜 2016年7月3日 - 16:51

尴尬,原来你下一篇就是写的就是资源文件,不过还是建议你在本教程中提到资源文件加载的事情,两篇教程应该是要同时使用的:)

回复
ben 2016年7月23日 - 23:02

编译没错,运行,功能正常,但是不会出现图标。检查了一遍找不到哪里错了,把图片格式换成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

回复
ben 2016年7月23日 - 23:07

前一个回复的qrc内容错了
//08.qrc

open.png

回复
ben 2016年7月23日 - 23:08

奇怪,为什么qrc的文件内容拷贝在回复框中,只显示"open.png"?

回复
ben 2016年7月23日 - 23:42

豆子能把文件夹和文件的排列显示一下吗?存放图片的images文件夹和QtCreator资源文件中的前缀images是一回事吗?

我用QtCreator创建的项目,也是没法显示图标啊,奇了怪了。

回复
ben 2016年7月24日 - 10:31

已经找到原因了: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图片

回复
豆子 2016年7月24日 - 11:28

使用 qrc 与不使用 qrc 是完全不同的:前者会编译成二进制代码,直接内嵌到 exe 中;后者会在运行时加载图片。二者适用于不同的场合:前者运行效率更高,但是不能由用户提供并切换;后者可以由用户提供图片并切换显示,适合于用户自定义主题等。

回复
ben 2016年7月25日 - 17:31

豆子的意思是说如下第2种办法是不使用qrc?
open_action = new QAction(QIcon(“../images/open”), tr(“&Open…”), this);

回复
豆子 2016年7月25日 - 21:29

是的,这样是运行时加载的(路径没有冒号)

回复
Fantasy 2017年2月10日 - 20:47

总结得不错,我也这样进行了实验,`.`是同级目录,`..`是上一级。

其实主要是觉得豆兄把prefix取名为images, `/images`很容易让人联想到这就是一个目录名或者图片的前缀都应该是images。

在此纠结很久,好歹试出来了。

接下来要跟这豆兄好好学

回复
t850508594 2016年8月8日 - 16:46

QMenu *file = menuBar()->addMenu(tr("&a"));
新手求教这句话能解释一下么 、menuBar指向addMenu是什么意思、可不可以像 QToolBar *toolBar = addToolBar(tr("&b"));这句话直接用addMenu?

回复
豆子 2016年8月12日 - 16:20

menuBar() 是函数调用,返回一个 QMenuBar 对象的指针,然后再去调用这个对象的 addMenu() 函数。等价于:

QMenuBar *mb = menuBar();
mb->addMenu(tr("&a"));

这个是 C++ 的基础内容,可以先学习下 C++ 的相关知识。

回复
augest rush 2016年11月22日 - 15:17

QMenu *file=menuBar()->addMenu(tr(“&a”));与QMenu *file=menuBar()->addMenu(tr(“a”)); 有什么区别??

回复
豆子 2016年11月26日 - 10:43

前面的 &a 会生成一个快捷键,Windows 平台下,按住 Alt 键会在 a 下面显示一个下划线;如果只是 a 的话就不会有这个快捷键。

回复
Fantasy 2017年2月10日 - 20:39

好棒

回复
ljl 2016年12月26日 - 15:43

您好,我在ubunu14.04系统下复制了上面内容,只有工具栏以及状态栏,没有显示菜单栏,也就是看不到“File”这个单词,想问问是什么原因?麻烦您了

回复
ljl 2016年12月26日 - 15:48

我知道了,哎,ubuntu的菜单栏,在最上面,抱歉一直没看到

回复
Fantasy 2017年2月10日 - 20:40

有一个问题不是很理解,“在堆上创建了openAction对象”,这个“堆”应该是与“栈”对应的,请问该如何理解

回复
豆子 2017年2月11日 - 09:07

使用 new 关键字创建的对象,都是在堆上面分配空间;否则都是在栈上面分配的

回复
Fantasy 2017年2月11日 - 09:38

这里 QAction *openAction,然后openAction = new QAction()

在QAction这个类的指针对象上新建一个实例(对象)QAction,第一个QAction是类名,第二个是函数名,这样理解对吗?

然后一个问题是,评论时是留下邮箱的,你回复了我的评论,并没有收到邮件反馈,有什么别的方法知道你给出了回复吗?

回复
QT learning 2017年3月14日 - 18:20

豆子老师,新手,为什么我把你的代码直接复制,mainwindow.h,mainwindow.cpp,main.cpp三个,运行了窗口却和之前一样,没有发生改变,没有菜单栏、工具栏等,我用的QT5.4.0,不知道哪里出问题了,麻烦您指教一下?

回复
豆子 2017年3月16日 - 22:06

有没有重新构建下试试?或者重新运行 qmake 之后再 build

回复
Qt之路 2017年7月6日 - 17:03

豆子大大,我的也是这个问题

回复
Qt之路 2017年7月6日 - 17:09

有菜单栏但是没有工具栏。而且addMenu()函数要么只能显示出图标,要么只显示“File”,没办法实现
QMenu *QMenuBar::addMenu(const QIcon &icon, const QString &title)
请豆子大大多指教~

回复
chou 2018年3月21日 - 19:53

老师您好 我的QT creator 用起来十分的卡 编辑页面点击没有反应 所以我用VS2015加插件的方式创建QT项目 但是创建后的项目中好像没有 mainwindows.h 和 mainwindows.app 只有main.cpp 项目名.cpp 项目名.h等 请问像上面的”QMainWindow中使用QAction” 应该怎么实现呢 感谢老师回复

回复
chou 2018年3月21日 - 19:59

老师我知道了 这个是之前指定的类名 我默认是和项目名一样啦

回复
chou 2018年3月21日 - 20:04

另外就是QT creator 的卡顿问题应该怎么办呢 在编辑页面上所有操作是有效的但是都不是直接显示 需要切到别的页面比如欢迎页再切回来才会显示之前的变化

回复
豆子 2018年3月25日 - 09:38

卡顿的问题不清楚是什么原因,估计要检查本机环境之类的了

回复
陈宇 2018年3月22日 - 17:16

为什么我会出现这个错误 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"));
^

回复
豆子 2018年3月25日 - 09:39

addToolar() 是 QMainWindow 的函数,是不是你在调用的时候不是 QMainWindow?

回复
2019年3月5日 - 15:48

运行时出现错误,调试时发现是在 mainwindow.cpp中的file->addAction(openAction);出错的,系统是macOS,Qt5.12.1

回复
2019年3月5日 - 16:10

我尝试改成这样的语句就不会在运行时终止
QMenuBar *file = menuBar();
file->addMenu(tr("&File"));
file->addAction(openAction);

回复
Rong_ggq 2019年5月6日 - 17:02

tr(“&File”)中加了个&,我去掉&后,程序也正常跑,请问一下这个&有什么意义么?一时没搞懂

回复
豆子 2019年5月8日 - 15:16

& 会将后面的字符变成快捷键。在 Windows 平台按下 Alt 键,会显示一个下划线,作为快捷键的标记。

回复
Kitty 2019年5月24日 - 07:45

豆子,请问下 Separate Action的功能是什么呢?

回复
Kitty 2019年5月24日 - 07:46

打错啦~是Separator Action

回复
Kitty 2019年5月24日 - 08:52

我懂啦~谢谢

回复
Li 2019年5月24日 - 10:04

老师,您好,为什么我运行时出现了17: error: undefined reference to `MainWindow::open()'错误。版本是Qt Creator 4.2.1

回复
mercuriex 2019年6月13日 - 22:46

请问QT自身的众多快捷键也是setShortcuts设置的吗?更改QT的快捷键时发生了什么?

回复
cxtan 2019年6月24日 - 13:57

豆子老师:
有个问题问下,
QMenuBar *qmenubar = new QMenuBar();
QMenuBar *qmenubar = menuBar();
这两种写法,有什么不同吗,第一种不能显示,第二种正常。

回复
豆子 2019年6月25日 - 13:29

第一种是使用构造函数创建,第二种是调用了 QMainWindow 的函数返回。menuBar() 已经把 QMenuBar 添加到窗口,所以可以直接显示,而构造函数创建之后,你需要手动添加到窗口才行

回复
cxtan 2019年6月26日 - 11:11

多谢豆子老师

回复
zz 2019年7月24日 - 11:13

:-1: error: [ui_mainwindow.h] Error 127
请教出现了错误,资源文件路径没有发现问题 看过下一节的资源文件说明

回复
zz 2019年7月24日 - 13:27

已经解决了 谢谢

回复
hbsyxyt 2019年9月11日 - 11:22

我也是找不到,谢谢你我也看到了!

回复
chen 2019年10月18日 - 16:52

作者大大,请问现在(2019年10月)这篇教程,会不会过时了,好像这个教程里没有用到设计师,是当时设计师还没用出吗?还是设计师没什么用。。。反正我用的qt4.3.0版本按照上面这个代码,在MainWindow类里面会出现一个UI对象

回复
豆子 2019年11月2日 - 16:33

没有,只是因为个人偏好没有使用设计师。其实设计师对于界面的快速开发还是很有帮助的,不过鉴于这系列文章是教程性质,所以没有引入过多的内容。另外,因为感觉设计师生成的代码可读性有些不好,个人很少使用设计师,所以也没有涉及这部分内容。

回复
Amoy 2020年1月19日 - 13:44

你好,我是小白一枚!复制粘贴你的代码,linux下运行没有显示菜单栏,想请教一下这是为什么,也没有报错!谢谢!

回复
豆子 2020年2月7日 - 16:53

linux 使用的什么桌面?QMenu 会按照具体的桌面去设置。如果你的桌面环境并没有每个窗口的菜单栏(类似 macOS),那么就会按照系统的显示来。窗口菜单栏可能被合并到桌面的公共菜单栏。

回复
Amoy 2020年2月13日 - 16:39

好的!谢谢!

回复
Amoy 2020年2月13日 - 16:41

确实合并到桌面的公共菜单栏了!

回复
Amoy 2020年2月13日 - 16:37

豆子哥,问一下!我在ubuntu16.04+qt5.7.1运行你的这篇代码,但是菜单栏没效果,工具栏和状态栏等其他都显示正常,这是为什么?谢谢!

回复
Mask 2020年3月14日 - 19:25

您好,怎么重新运行qmake呢,我把图片路径改为绝对路径,点了绿三角编译运行后还是没出来,是需要重新qmake吗

回复
豆子 2020年4月21日 - 13:25

点右键可以运行 qmake

回复
成年雄性大熊猫 2021年3月17日 - 11:38

您好,请问为什么创建项目的时候要是带了.ui文件,就显示不了菜单栏呢?
或者是因为什么别的原因

回复
李泳杰 2021年8月6日 - 15:34

cpp里的最后这句statusBar();在QT5.14.1里可以去掉液没有影响。

回复
veni 2021年10月23日 - 21:56

补充一下:Qt新建项目的时候会在MainWindow的构造函数里自动添加ui->setupUi(this);这一句,如果菜单栏的相关代码在这一句之前,就会导致显示不出来菜单栏。把ui->setupUi(this)移到开头就行。

回复
littlepriest 2023年8月16日 - 10:33

最新的 qt6 里,那个 menuBar 出不来了。。

回复
littlepriest 2023年8月16日 - 14:12

有了 看错了。

回复

回复 Kitty 取消回复

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2