QT的GUI设计

Python Qt GUI设计入门(一) 文章目录前言一、Qt 简介以及安装二、PyQt5 安装三、在PyCharm中直接编写代码创建GUI四、在Qt中创建py文件总结 前言 博主最近在学习Python,但是苦于没有实践动手的机会,所以就顺便练习一下GUI设计,趁此机会锻炼一下Python的熟练度。软件请自行下载,Python3.9+Qt 5.12 以下是本篇文章正文内容,系列文章仅为学习记录,并不作为教程,有建议可以在评论提出,私信一般不回复。 一、Qt 简介以及安装 简单介绍Qt 以及响应的环境安装 Qt 简介 Qt是一个跨平台的 C+ 阅读详情

原文地址:http://guiliblearning.blogspot.com/2009/04/qt-gui.html

作者: demonstrate

最早接触到这类设计其实是从Borland C++ Builder 开始的,作为一个所谓的快速开发工具,其实我对其实现界面设计那块到现在都没有清晰的理解。后来接触了Java 一段时间,那时候只懂得自己设计界面就是继承一个类,如主窗口或者 applet,然后在该类中添加很多其他的 component 作为其 protected 成员。可是很少考虑到怎么更方便的设计。因此,可以说接触到第一个这种设计思想的GUI 库就是在 Qt 了。 不得不说 Qt 其实和 Java 很像,虽然说 Qt 是 C++ 写成,但是注意到它其实是单一祖先 QObject 一脉相承,通过 QMetaObject 实现的RTTI,这多多少少和Java单一祖先一致,但是 Qt 不排斥使用其他的 C++ class,只是失去了 signal/slot 机制。在 moc 的 man page 里面,其实介绍了 Qt 实现的种种局限性:

  • 我们无法使用 template 继承 QObject,换言之,下面代码无法被 moc 转换成为有效的 C++ compiler 可编译代码:
     template<class>  
 
     class TemplateClass : public QObject {  
           Q_OBJECT  
           // ...
     public slots:  
          // ...
     } ;class> 

  • 使用 multiple inheritance 必须把 QObject 或者其子类放在第一个父类的位置(因为使用 Q_OBJECT 需要覆盖),然后继承别的类。颠倒后,如 g++ 会抱错,如
     multiclass.hpp:17: Warning: Class MultiClass inherits from two QObject subclasses NoneQtClass and QObject. This is not supported!
     moc_multiclass.cpp:39: error: ‘staticMetaObject’ is not a member of ‘NoneQtClass’
     moc_multiclass.cpp: In member function ‘virtual void* MultiClass::qt_metacast(const char*)’:
     moc_multiclass.cpp:55: error: ‘qt_metacast’ is not a member of ‘NoneQtClass’
     moc_multiclass.cpp: In member function ‘virtual int MultiClass::qt_metacall(QMetaObject::Call, int, void**)’:
     moc_multiclass.cpp:60: error: ‘qt_metacall’ is not a member of ‘NoneQtClass’
     make: *** [moc_multiclass.o] Error 1

         MultiClass 继承 QObject 和 NoneQtClass,插入的 Q_OBJECT 展开后,因为将 NoneQtClass 放在第一位后 MultiClass 的结构已经不是 QObject 在前面所以创建staticMetaObject 出错,后面虚函数表也因为在后面所以导致使用的其实是前面那个 class 的 vtable。

  • 函数指针不能作为 signal/slot 的参数,这个可以用 typedef 克服,如
    class SomeClass : public QObject 
    {  
             Q_OBJECT  
              //...
    public slots:  
            // illegal
             void apply( void (*apply)(List *, void *), void * );  
    }; 

    将被认为非法(主要是判断参数类型时会失败,记得 QMetaObject 存下来的是什么信息么?),但是

    typedef void (*ApplyFunctionType)( List *, void * );  
    
    class SomeClass : public QObject 
    {  
             Q_OBJECT  
             //...
    public slots:  
             void apply( ApplyFunctionType, char * );  
    }; 

    是可行的。

  • 友元声明最好不要放在 signal 和 slot 声明中,这很明显,因为多数情况下虽然根据宏替换, signals: 被替换为 protected:,slots 被替换为空,但是编译器处理 friend 可能并不完全这样无关的处理,理论上说标准的编译器应该能 work,如 g++ 4.3.3.
  • signal 和 slot 不能被 upgrade,这是因为 moc 需要一个完整的函数声明,而提升的时候声明是不完整的,如
    class SlotClass : public QObject 
    {  
             Q_OBJECT  
    protected slots:  
             int getValue() ;  
    } ;  
    
    class UpgradeSlotClass : public SlotClass 
    {  
             Q_OBJECT  
    public slots:  
             Slot::getValue ;  
    } ;  

    其中的 Slot::getValue 的提升在正常的情况是被允许的,可见报错的是 moc,

    /usr/bin/moc-qt4 -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. upgradeslotclass.hpp -o moc_upgradeslotclass.cpp
    upgradeslotclass.hpp:15: Error: Not a signal or slot declaration
  • signal 和 slot 的参数不能使用宏,这是因为 moc 不展开宏
  • 嵌套类声明不应该出现在 signal 或者 slot 里面,也是因为 moc 不能处理的原因。
  • 构造函数不应出现在 signal 和 slot 里面,虽然是函数,但是没有必要。
  • Q_PROPERTY 宏声明属性时应在包含其读写函数的 public 节之前,写在同一个 public 里面不允许,注意
    #define Q_PROPERTY(text)

    其实在类声明时这句话没有任何作用,只是 moc 编译会产生对应的代码,而 moc 要求这部分必须以类似下面的方式书写

    class PropertyClass : public QObject 
    {  
             Q_OBJECT  
             Q_PROPERTY( int value READ getValue WRITE setValue )  
             int value ;  
    public:  
              PropertyClass() ;  
              void setValue( int = 0 ) ;  
              int getValue() const ;  
    } ;  

    这部分对应 moc 会产生如下代码

      int PropertyClass::qt_metacall(QMetaObject::Call _c, int _id, void **_a)  
      {  
          _id = QObject::qt_metacall(_c, _id, _a);  
          if (_id < _c ="=" _v =" _a[0];" _c ="=" _v =" _a[0];" _c ="=" _c ="=" _c ="=" _c ="=" _c ="=" _c ="=">  

          为什么在 QMetaObject 中提供支持 property 以及 Q_CLASSINFO 这些看起来完全没必要的东西呢?后者比如

      Q_CLASSINFO("Version", "3.0.0")  

这些其实从一个方面是对 GUI 设计程序提供支援。Qt 提供的 GUI 设计程序叫 Qt Designer(似乎 Qt Creator 也能 design),这是一个图形界面,将需要的 widget 拖到窗口上,用适当的 layout 组织起来,在每一个 widget 被点中的时候有一个 property editor,可以在这里设置前面使用 Q_PROPERTY 声明并且是 DESIGNABLE 为 true 的属性,这就是所谓的 widget editing mode。另外还有 signal and slot editing mode,这里可以直接把发出 signal 的 widget 拖向 slot 的 widget,这会产生一根箭头,然后填写对应的 signal 和 slot 即可。在 buddy editing mode 里,我们将一些原则上不接受键盘响应 widget 拖向相关接受键盘响应的 widget,这将让他们具有等效力的处理键盘的能力。在 tab order mode 里面我们设置按 TAB 时遍历的顺序。另外还有 resource editor 供我们管理资源,如使用的图片,action editor 让我们编辑菜单上的 action(最后将菜单项 or 工具栏与之连接)。新加入的 QUiLoader 类允许 Qt 能像 glade 一样处理 XML 文件描述的界面,并动态生成。

Qt 提供的当然远远不止仅仅一些 widget(与 gtkmm 相比),它还提供了对 accessibility、数据库 SQL、网络模块等等的支持,这个我们会在后文讨论。这里集中讨论 Qt designer 一些设计上的特性。

Qt Designer 里面可以预览 skin、添置自己的类似 CSS 的 stylesheet 将 widget 改变样式,这可以用 settings -> preference -> form 里面的 preview 打开,或者直接点某个 widget 的 styleSheet 自己添加。Qt 里面常用的 container 有 Frame、GroupBox、StackedWidget、TabWidget、ToolboxWidget、DockWidget,我们可以在里面放其他的 widget。

Qt 设计菜单和工具栏很简单,界面和功能是分开设计的,界面在编辑状态依照要求点击对应的地方就可以增加菜单项,菜单里面 & 可以产生一个键盘操作,如 &File 就会使得当菜单打开后按 F 调用该菜单。类似的,添加工具栏后可以在上面增加一些按钮。功能是用 Action Editor 编辑的。

下面我们来看如何利用 Qt Designer 设计的界面和我们的程序结合起来。首先要了解 Qt Designer 输出的 .ui 文件最后会被如何处理,这是 uic 程序所处理的,这会产生一个 .h 文件,比如 mywindow.ui 会产生一个 ui_mywindow.h 文件,该文件包含两个部分,一个是 Ui_MyWindow 类,这个类其实仅仅包含除了顶层 widget 以外所有的 widgets,比如我们的窗口用 QMainWindow 或者 QWidget 类,里面有若干 layout、button 等,那么产生的 Ui_MyWindow 类含有除了 QMainWindow 或 QWidget 外所有其他 components 的指针,并通过 setupUi( QMainWindow *) 方法将我们设计的界面呈现在指定的顶层 widget 上。另外在 Ui 名域空间声明了一个 MyWindow 类,继承 Ui_MyWindow,这是为了避免 namespace pollution。因此,预览我们窗体最简单的方法是用如下代码,

#include "ui_main.h"

int main( int argc, char *argv[] )  
{  
  QApplication app( argc, argv ) ;  
  QMainWindow *widget = new QMainWindow ;  
  Ui::MainWindow ui ;  
  ui.setupUi( widget ) ;  
  widget -> show() ;  
  return app.exec() ;  
}  

我们会在后面详细分析这里面相关代码,这里注意通过 new 产生一个 QMainWindow,然后注意用 Ui::MainWindow 产生一个仅仅生成代码的类实体,并且调用 setupUi() 方法在 widget 上产生我们需要的界面。最后调用 widget 的 show() 方法,并用 app.exec() 开始进入消息循环。

这里插一段关于 widget 释放的问题,注意 ui 里面通过调用 new 产生的控件在 widget 被摧毁的时候一起被摧毁,ui 里面并没有析构这些,因为其实最后都是 dangling pointer,这是很危险的,千万不要多做这一步。另外关闭窗口时会触发 QMainWindow::close() 这个 slot,这会析构窗体(如果设置 QWidget::DeleteOnClose 属性)。

可是我们在 Qt Designer 里面最多加入很简单的 signal/slot 连接,还有很多功能我们并不是在 Qt Designer 里面实现的,因此,我们需要用别的方式才能在不修改这部分自动生成代码的基础上实现自己的功能。最简单的办法就是单继承窗体类,把界面作为一个私有成员,

class MyWindow : public QMainWindow 
{  
        // ...
private:  
        Ui::MyWindow ui ;  
} ;  

这样在构造 MyWindow::MyWindow() 时通过 ui(this) 就可以创建自己的界面,然后进一步通过 QObject::connect() 等函数修改 signal/slot 连接。但是连接必须通过成员 ui 进行。

更方便的做法是使用多重继承

class MyWindow : public QMainWindow, private Ui::MyWindow 
{  
         // ...
public:  
         MyWindow( QWidget *p ) : QMainWindow(p), Ui::MyWindow() {  
         setupUi( this ) ;  
         // ...
         }  
} ; 

这时我们可以直接对 MyWindow::component 进行 connect。不过值得注意的是 connect 只能在 QObject 之间进行无法传递给非 QObject 对象,也无法 connect 到一般的函数。

另外一种就是和 glade 实现的类似,

QWidget* TextFinder::loadUiFile() 
{  
      QUiLoader loader;  

      QFile file(":/forms/textfinder.ui");  
      file.open(QFile::ReadOnly);  

      QWidget *formWidget = loader.load(&file, this);  
      file.close();  

      return formWidget;  
}  

注意这样动态加载的不能使用 formWidget -> member 的形式调用,我们应该利用 QObject::objectName() 来搜索获得对应的地址,如

ui_findButton = qFindChild(this, "findButton"); 

我们后面会比较 gtkmm 在实现类似的功能上的区别。

创建 connection 最土的办法就是手工创建,因为前面说必须 connect 到一个 QObject 上,所以最直接的做法如下

ImageDialog::ImageDialog(QWidget *parent)  
     : QDialog(parent)  
{  
      setupUi(this);  
      okButton->setAutoDefault(false);  
      cancelButton->setAutoDefault(false);  
      // ...
      connect(okButton, SIGNAL(clicked()), this, SLOT(checkValues()));  
 }  

把 slot 就放在多重继承 QObject 的 private slots 里,但是 Qt 可以利用 QMetaObject 实现自动的连接,这是用约定的 on_objectName_signal 定义的 slots,用 QMetaObject::connectSlotsByName(QObject *) 连接,如多重继承的情况下,取 this,而从 ui 文件产生的界面用 QUiLoader::load() 返回的 widget 指针。一般用 uic 产生的代码会自动调用该函数。

ROS项目开发实战(三)——使用QT进行ROS的GUI界面设计(详细教程附代码!!!) 序     本篇博客主要介绍怎么使用qt对ros进行gui设计与调试,包括使用列表视图显示ROS话题发布与接收的消息,点击QT按钮按钮进行ros消息的发布。 在阅读本文之前没有安装QT与配置环境可以参考博文:如何用Qt的对ROS项目进行调试及创建GUI界面。 最近有个项目需要对ROS进行GUI设计,而ROS在这方面开发教程实在是很少,去师兄那里取经之后就开始干活了,现将自己的详细经验分享。 ... 阅读详情

相关推荐

C++/Qt GUI程序设计基础

基于Qt框架的C++编程,本章的主要内容包含GUI项目文件组成、可视化UI设计

qq_67853786的博客 1294

使用Qt Designer进行Python GUI设计

Qt Designer提供了直观的界面和预定义的GUI元素,使我们能够快速创建和设计GUI。然后,我们可以使用生成的Python代码将设计文件加载到我们的应用程序中,并显示GUI界面。Qt是一个流行的跨平台应用程序开发框架,它提供了Qt Designer工具,使我们能够轻松地创建和设计GUI设计完成后,我们需要将GUI设计保存为.ui文件,以便稍后在Python代码中使用。在设计过程中,可以使用Qt Designer的属性编辑器来设置每个元素的属性,如大小、位置、文本等。

CodeHeroicX的博客 308

QT Designer 设计Gui 及其好处

1.      用Qt Designer来设计GUI)            创建并初始化子窗。 (2)            把子窗口部件放到布局中。 (3)            设置Tab键顺序。 (4)            建立信号-槽之间的连接。 (5)            实现对话框中的自定义糟。

辉哥哥的专栏 4879

Qt报错】error: Not a signal or slot declaration

Qt报错】error: Not a signal or slot declaration

qq_49372719的博客 3715

QThread 与 QObject的关系?

Threads and QObjects QThread 继承 QObject.。它可以发送started和finished信号,也提供了一些slot函数。 QObject.可以用于多线程,可以发送信号调用存在于其他线程的slot函数,也可以postevent给其他线程中的对象。之所以可以这样做,是因为每个线程都有自己的事件循环。 在进行下面的讲解之前,应该了解的重要的一点是:QThread...

weixin_34381666的博客 184

QT报错】 Error:Not a signal or slot declaration

然后,槽函数定义和实现并没有问题: 后来查阅资料了解到,问题出现在这里: 我在public slots下还定义了一个成员变量,造成错误。 正确方式就是将成员变量放到public slots之前即可:

sazass的博客 4523

error: C2039: “staticMetaObject”: 不是“QGraphicsItem”的成员

当使用Qt的图形视图框架时,自定义图形类时,一般这样写 class myItem:public QGraphicsItem { public: myItem(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const; }; 然而有些时候,我们需要使用信号与槽,就需要增加 Q_OBJECT,这时,就会报错 error: C2039:

weixin_44103773的博客 1455

error: 'staticMetaObject' is not a member of 'QGraphicsItem'

error: 'staticMetaObject' is not a member of 'QGraphicsItem' 在类定义的时候,增加下面的描述: class MyItem:public QObject,public QGraphicsItem {     Q_OBJECT public:     explicit MyItem(); ...... }...

hongyd的博客 2902

qt-GUI 程序设计基础

信号与槽是 Qt 编程的基础,也是 Qt 的一大创新。有了信号与槽的编程机制,在 Qt 中处理界面上各个组件的交互操作就变得比较直观和简单。信号(signal)是在特定情况下被发射的通知,例如 QPushButton 较常见的信号就是点击鼠标时发射的 clicked()信号。GUI 程序设计的主要工作就是对界面上各组件的信号进行响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。槽(slot)是对信号进行响应的函数。槽就是函数,所以也称为槽函数。

pxxzhk的博客 1290

Python Qt GUI设计:专栏总述

本专栏基于Python语言,侧重于具有GUI效果的上位机项目开发,可实现和硬件设备的数据交互通信。

不脱发的程序猿 4452

QT界面GUI设计之选择文件并显示

QT界面GUI设计之打开图片并显示 准备做一个Qt的界面,只是实现了基本功能,但是各种相关细节还没有做到位,今天凑了半天论文,毫无进展,下午把QT界面又拿出来研究了一下,主要是打开文件选择图片后显示。 主要步骤呢,其实很简单,Qt内置一个打开文件的函数 static QString getOpenFileName(QWidget *parent = nullptr, ...

爆炒小肥牛 7012

使用Qt Creator进行GUI设计和开发

在本文中,我们将使用Qt Creator创建一个简单的GUI应用程序,该应用程序包含一个按钮和一个标签。我们将使用Qt Creator的“窗体设计器”来设计应用程序的用户界面,并使用C++代码编写应用程序的行为。首先,我们将打开Qt Creator,并选择“文件”>“新建文件或项目”>“应用程序”>“Qt Widgets应用程序”。然后,在mainwindow.cpp文件中,我们需要在构造函数中初始化按钮和标签,并将它们添加到主窗口中。在“类”字段下,选择“QWidget”,这将创建一个空白窗口。

cl6789的博客 378

python qt gui教程_Python GUI教程(四):安装并使用Qt设计设计Python GUI

一、安装PyQt5 设计师工具安装默认情况下,我们在安装PyQt5的时候会自动安装Qt设计师软件:如果没有安装的,我们可以使用Python包管理工具pip进行安装:pip install pyqt5-tool安装完成后,qt设计师会出现在python的pyqt5模块目录下:双击运行,会直接打开Qt设计师软件,这样就已经安装好了:二、使用Qt Designer创建GUI窗口打开qt设计师之后,我们可...

weixin_39998462的博客 720

GUI 主循环设计及其在 MiniGUI, GTK, QT 的实现

GUI 主循环设计及其在 MiniGUI, GTK, QT 的实现作者: 刘鹏日期: 2009-05-22介绍了 GUI 主循环的设计思路,并分析了 MiniGUI, GTK, QT 的主循环。简介我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事

linux嵌入式驱动软件开发 1741

Qt Designer设计GUI原理及调用过程

由于在GUI界面设计过程中,会涉及到很多界面的布局和美化等操作,为了方便获得“所见即所得”的设计效果,Qt提供了Qt Designer(Qt设计师) 工具可以用来直接对界面进行可视化设计设计之后就可以利用Qt的一些编译工具,生成对应的代码,方便在程序中调用。 大家如果用过Visual Studio下的MFC就会对这种界面设计方式非常熟悉了,但是Qt Designer提供的方式更加灵活好用。 话不...

zhanghm1995的博客 4256

QT Designer GUI设计与开发实战指南

在本章中,我们将为您介绍Qt Designer这一强大的跨平台GUI设计工具。Qt Designer允许开发者以直观、可视化的方式构建和定制用户界面,无论您是初学者还是有经验的开发者,都能够通过Qt Designer快速构建出美观、功能丰富的界面。Qt Designer是Qt框架的一部分,它是专门用于设计和布局图形用户界面(GUI)的工具。它提供了一套完整的可视化编辑器,可以让你拖放各种控件来设计窗口、对话框和其他用户界面元素,无需编写大量代码即可实现界面的初步构建。

weixin_31974443的博客 1373

三种方法在ROS中加载Qt库进行GUI设计

编写ros程序,因为有时会涉及到界面设计,所以本人主要用的QtCreator IDE。首先当然是安装QtCreator,这个网上有很多安装教程和下载资源,非常简单。由于Qt的工程大多采用qmake对.pro文件进行编译,而在ros工程中运用的是catkin_make(实际也是对cmake的一个封装,语法都一样),因此很有必要了解下如何用cmake去写Qt工程,这里给个链接(Qt_Cmake_Man...

welin的博客 1万+

QT界面GUI设计之背景和按钮美化

QT界面GUI设计之背景和按钮美化环境配置背景设计背景渐变色背景图片按钮样式Label添加图片 好几天没更博客了,今天更新一下关于Qt页面搭建后的美化工作。众所周知,Qt这款软件GUI功能可谓是十分强大,以前只是简单的设计出来之后,草草了事,这几天把美化细节学习了一下,抽空记录下来,以便后期需要,便于翻阅。 依旧先上图: 环境配置 VS2017 QT4.9.0 关于环境配置我就不多说了,网上...

爆炒小肥牛 9275
上一篇: OO设计原则总结
下一篇: GTKMM 对比Qt
鹅鹅
博客等级 码龄19年 70粉丝 53原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值