假设要做一个简单的小窗口(如下图所示),PyQt 和 C++ 要用多少代码可以完成呢?
注:本文内容较多(主要是 C++ 的部分),若有必要请直接跳到最后看结论。
一、 C++ 版本
除了最基础的 pro 文件之外,我一共创建了 5 个文件:
customlabel.h
-
customlabel.cpp
(处理标签Label的右键响应,以及其菜单) mainform.h
-
mainform.cpp
(主界面窗口) -
main.cpp
(主程序入口)
以下这 5 个文件的内容都是完整版,可以直接复制过去。
1. customlabel.h
一个可以响应鼠标右键点击的标签。
#ifndef CUSTOMLABEL_H
#define CUSTOMLABEL_H
#include <QMenu>
#include <QLabel>
#include <QLineEdit>
#include <QAction>
#include <QWidget>
#include <QVBoxLayout>
#include <QWidgetAction>
#include <QMouseEvent>
#include <QString>
/* ------------------
* QWidgetAction
* 这东西可以把输入框显示在菜单项上
* ------------------*/
class CustomWidgetAction: public QWidgetAction
{
Q_OBJECT
public:
explicit CustomWidgetAction(QWidget *parent);
QLineEdit * editline;
QVBoxLayout * vlayout;
QWidget * widget;
QWidget * createWidget(QWidget *w) override;
};
/* ------------------
* 可以用右键点击的标签,拥有自己的右键菜单
* ------------------*/
class CustomLabel : public QLabel
{
Q_OBJECT
public:
CustomLabel(QString s);
QMenu * menu;
QAction * nmaction;
CustomWidgetAction * waction;
void mousePressEvent(QMouseEvent *e) override;
};
#endif // CUSTOMLABEL_H
2. customlabel.cpp
#include "customlabel.h"
#include <QCursor>
CustomWidgetAction::CustomWidgetAction(QWidget *parent)
:QWidgetAction(parent)
{
editline = new QLineEdit(tr("这里可以显示中文"));
vlayout = new QVBoxLayout();
vlayout->addWidget(editline);
widget = new QWidget();
widget->setLayout(vlayout);
}
QWidget* CustomWidgetAction::createWidget(QWidget *w)
{ // 必须要有这个函数,用来获得需要显示的控件
widget->setParent(w);
editline->setFocus();
return widget;
}
CustomLabel::CustomLabel(QString s):QLabel(s)
{
waction = new CustomWidgetAction(this);
menu = new QMenu(this);
menu->addAction(waction);
}
void CustomLabel::mousePressEvent(QMouseEvent* e)
{
if (e->button() == Qt::RightButton)
menu->exec(QCursor::pos()); // 当点击右键时显示菜单
}
3. mainform.h
主窗口。
#ifndef MAINFORM_H
#define MAINFORM_H
#include <QDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLineEdit>
#include "customlabel.h"
class MainForm : public QDialog
{
Q_OBJECT
public:
explicit MainForm(QWidget *parent = nullptr);
QPushButton * button;
QLineEdit * editbox;
CustomLabel * label;
QVBoxLayout * vlayout;
};
#endif // MAINFORM_H
4. mainform.cpp
#include "mainform.h"
MainForm::MainForm(QWidget *parent) : QDialog(parent)
{
resize(320, 240);
setWindowTitle("Test QWidgetAction");
editbox = new QLineEdit(tr("This box can input any languages."));
label = new CustomLabel(tr("Right click on me to show popup menu."));
button = new QPushButton(tr("Close"));
vlayout = new QVBoxLayout(this);
vlayout->addWidget(editbox);
vlayout->addWidget(label);
vlayout->addWidget(button);
connect(button, SIGNAL(clicked()), this, SLOT(close()));
}
5. main.cpp
程序入口。
#include "mainform.h"
#include <QApplication>
int main(int argc, char* argv[])
{ // Qt 程序入口
QApplication app(argc, argv);
MainForm form;
form.show();
return app.exec();
}
以上是 C++ 版 Qt 的代码,洋洋洒洒一大篇,虽然很有成就感,但也花费了不少时间。
二、 Python 版本
只用一个文件:
from PyQt5 import QtWidgets, QtGui, QtCore
class MyWidgetAction(QtWidgets.QWidgetAction):
def __init__(self, parent):
super().__init__(parent)
self.editbox = QtWidgets.QLineEdit('直接显示中文是没有问题的。')
self.vlayout = QtWidgets.QVBoxLayout()
self.vlayout.addWidget(self.editbox)
self.widget = QtWidgets.QWidget()
self.widget.setLayout(self.vlayout)
def createWidget(self, parent):
self.widget.setParent(parent)
self.editbox.setFocus()
return self.widget
class MyLabel(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.setText('Right click on me to show popup menu.')
self.waction = MyWidgetAction(self)
self.menu = QtWidgets.QMenu()
self.menu.addAction(self.waction)
def mousePressEvent(self, e):
if e.button() == QtCore.Qt.RightButton:
self.menu.exec_(QtGui.QCursor.pos())
app = QtWidgets.QApplication([])
dlg = QtWidgets.QDialog()
txt = QtWidgets.QLineEdit('This box can input CJK characters.')
lbl = MyLabel()
btn = QtWidgets.QPushButton('Close')
btn.clicked.connect(dlg.close)
vbl = QtWidgets.QVBoxLayout(dlg)
vbl.addWidget(txt)
vbl.addWidget(lbl)
vbl.addWidget(btn)
dlg.resize(320, 240)
dlg.show()
app.exec_()
不得不说 Python 这东西真是方便,只要一个文件、不到 50 行代码就能实现!
你更喜欢哪一种?🤔🤔
这只是个小应用,Python 的开发效率明显高出不少。不过随着项目越来越庞大,Python 作为动态语言的弊端也逐渐显现,复杂场景中的错误可能会变得不可控。控制台上出错顶多抛出一个异常,使用者还能现场纠错,但 GUI 程序可是会闪退的啊!不过想想 C++ 应用也会毫无预兆地 crash,我不禁又陷入了沉思……
(完)