C++ GUI Programming with Qt4 Second Edition 之 附录C.1 Qt Jambi入门

2023-05-16

Qt Jambi入门

      本节,我们将开发一个简单的Java应用程序并显示如图C.1所示的窗口。除窗口标题之外,Jambi Find对话框与第二章中创建的Find对话框的外观和功能均相同。通过使用相同的例子,可以更容易地看出C++/Qt和Qt Jambi编程中的不同点和相同点。在讲解代码的同时,我们也会介绍出现的C++和Java概念上的区别。


图C.1 Jambi Find对话框

      Jambi Find程序的实现代码在一个单独的文件中,文件名为FindDialog.java。我们将分片介绍文件内容,首先从import声明开始。

import com.trolltech.qt.core.*;

import com.trolltech.qt.gui.*;

      这两个import声明将Qt所有的核心类和GUI类都引入了Java。其他的类集可以通过相同的import声明引入(如import com.trolltech.qt.opengl.*)。

public class FindDialog extends QDialog {

      与C++版本的例子相同,FindDialog类是QDialog的一个子类。在C++中,信号要在头文件里声明,依靠moc工具生成支撑代码。在Qt Jambi中,用Java的内省技术实现信号槽机制。但我们仍需要一些声明信号的方法,这可以使用SignalN类实现:

public Signal2<String,Qt.CaseSensitivity> findNext = new Signal2<String,Qt.CaseSensitivity>();

public Signal2<String,Qt.CaseSensitivity> findPrevious = new Signal2<String, Qt.CaseSensitivity>();

      共有10个SignalN类——Signal0、Signal1<T1>……Signal9<T1……T9>。类名中的数字表明了它们接受多少个参数,类型T1……T9指定了参数类型。这里,我们声明了两个信号,每个信号包含两个参数。两个信号的第一个参数是Java String类型,第二个参数是Qt.CaseSensitivity类型(这是一个Java的枚举类型)。在Qt API中的所有QString,在Qt Jambi中均用String替代。

      与其他的SignalN类不同,Signal0不是一个泛型类。要使用Signal0创建一个不含参数的信号,可以像下面这样:

public Signal0 somethingHappened = newSignal0();

      信号创建完成后,我们来看构造函数的实现。函数太长,我们将其分成三部分讲解。

public FindDialog(QWidget parent) {

       super(parent); 

label = new QLabel(tr("Find &what:"));

lineEdit = new QLineEdit();

label.setBuddy(lineEdit); 

caseCheckBox = new QCheckBox(tr("Match&case"));

backwardCheckBox = newQCheckBox(tr("Search &backward")); 

findButton = newQPushButton(tr("&Find"));

findButton.setDefault(true);

findButton.setEnabled(false); 

closeButton = newQPushButton(tr("Close"));

      在Java中创建窗口部件与C++唯一不同的是细微的语法细节。要注意的是,tr()的返回值是String类型,而不是QString。

lineEdit.textChanged.connect(this,"enableFindButton(String)");

findButton.clicked.connect(this,"findClicked()");

closeButton.clicked.connect(this,"reject()");

      Qt Jambi连接信号槽的语法与C++/Qt有点不同,但依然很简短。通常语法如下:

sender.signalName.connect(receiver,"slotName(T1, ..., TN)");

      与C++/Qt不同,我们不需要给信号指定签名。如果信号包含的参数多于它所连接的槽函数,那这些多出来的函数会被忽略。此外,在Qt Jambi中,信号槽机制不止限于在QObject子类中应用,任何继承QSignalEmitter的类都可以发出信号,任何类的任何函数都可以作为槽函数。

QHBoxLayout topLeftLayout = newQHBoxLayout();

topLeftLayout.addWidget(label);

topLeftLayout.addWidget(lineEdit); 

QVBoxLayout leftLayout = new QVBoxLayout();

leftLayout.addLayout(topLeftLayout);

leftLayout.addWidget(caseCheckBox);

leftLayout.addWidget(backwardCheckBox);

QVBoxLayout rightLayout = new QVBoxLayout();

rightLayout.addWidget(findButton);

rightLayout.addWidget(closeButton);

rightLayout.addStretch(); 

QHBoxLayout mainLayout = new QHBoxLayout();

mainLayout.addLayout(leftLayout);

mainLayout.addLayout(rightLayout);

setLayout(mainLayout); 

setWindowTitle(tr("Jambi Find"));

setFixedHeight(sizeHint().height());

}

      窗口布局代码实际上与原始的C++代码完全一样,用相同的布局类以完全相同的方式实现相同的功能。Qt Jambi中也可以通过Qt Designer以窗体形式创建对话框,然后用juic(Java用户接口编译器)编译,我们将在下节讲解这种方法。

private void findClicked() {

   String text = lineEdit.text();

   Qt.CaseSensitivity cs = caseCheckBox.isChecked()

           ? Qt.CaseSensitivity.CaseSensitive

           : Qt.CaseSensitivity.CaseInsensitive;

    if(backwardCheckBox.isChecked()) {

      findPrevious.emit(text, cs);

    }else {

      findNext.emit(text, cs);

    }

}

      Java关于枚举值的语法比C++稍微复杂点,但很容易理解。调用SignalN对象的emit()函数并传递正确类型的参数即可触发信号。类型检查在程序编译过程中完成。

private void enableFindButton(String text) {

findButton.setEnabled(text.length() != 0);

}

      enableFindButton()函数的功能和使用与C++源码相同。

private QLabel label;

private QLineEdit lineEdit;

private QCheckBox caseCheckBox;

private QCheckBox backwardCheckBox;

private QPushButton findButton;

private QPushButton closeButton;

      为了保持与本书其他部分代码的一致,我们将所有的窗口部件声明为类的私有成员。这仅仅是风格的问题,没什么可以阻止我们在构造函数中声明那些只在构造函数中用到的部件。比如,我们可以在构造函数中声明label和closeButton,因为没有其他地方引用它们。构造函数结束时也无需回收它们占用的资源。这是因为Qt Jambi使用与C++/Qt相同的父子类关系机制,所以一旦label和closeButton被创建出来,FindDialog窗口就获得了它们的所有权,并在内部保留其引用来保证它们的生命周期。QtJambi递归删除子窗口部件,一旦最顶层的窗口被删除,该窗口会反过来删除它所有的子部件和布局,这些子部件和布局又删除它们的子部件和布局,依次类推,直至清除完毕。

使用Java资源系统

      与大多数Java标准类不同,Qt Jambi深度支持Java的资源系统。Java资源由classpath:前缀定义。在Qt Jambi API中任何地方用到的文件名都可以用指定的Java资源代替,比如:

QIcon icon = new QIcon("classpath:/images/icon.png");

if (!icon.isNull()) {

    ...

}

      为找到需要的图标,Qt Jambi会搜索每个目录下的每个image文件夹或搜索由CLASSPATH环境变量指定的.jar文件。一旦找到icon.png图标文件,即结束搜索并使用所找到的文件。

      如果指定的文件不存在,程序也不会报错。在上面的例子中,如果没有找到icon.png,icon.isNull()会返回true。像QImage和QPixmap这种有构造函数的类,其构造函数包含一个文件名参数,我们可以使用isNull()函数检测指定的文件读取是否成功。在QFile中,我们用QFile.error()检查文件是否被读取。

      与AWT、SWing、SWT不同,Qt Jambi充分利用Java的碎片资源回收功能,如果删除了最顶层窗口的最后一个引用,系统会自动安排对这个窗口碎片资源的回收,而不需要显式的调用dispose()。这种方式非常方便,工作机制与C++/Qt相同。需要重点提醒的是,对于SDI(单文档界面)程序,必须保留所创建的每个顶层窗口的引用,以免它们被回收(在C++/Qt中,SDI程序通常使用Qt::WA_DeleteOnClose属性防止内存泄漏)。

public static void main(String[] args) {

       QApplication.initialize(args);

       FindDialog dialog = new FindDialog(null);

       dialog.show();

       QApplication.exec();

    }

}

      为方便起见,我们所提供的FindDialog带有main()函数,main()函数实例化了一个对话框并将其显示出来。声明行importcom.trolltech.qt.gui.*确保了我们可以使用静态的QApplication对象。Qt Jambi程序开始时,必须调用QApplication.initialize()并将命令行参数传递进去。QApplication对象可以处理它支持的参数,比如-font和-style。

      创建FindDialog时,将null作为父类传递进去表示所创建的对话框是顶层窗口。一旦main()函数结束,对话框即会消失,其资源也会被回收。调用QApplication.exec()开始事件循环,只有用户关闭对话框时,事件循环才会将控制权返还给mian()函数。

      虽然Qt Jambi API与C++/Qt API很相似,但仍有区别。比如,在C++中,QWidget::mapTo()成员函数有如下定义:

QPoint mapTo(QWidget *widget, const QPoint&point) const;

     其中QWidget作为变量指针传递,但QPoint却是常量引用。在Qt Jambi中,等效的函数定义如下:

public final QPoint mapTo(QWidget widget,QPoint point) { ... }

      因为Java中没有指针,所以在函数定义中并不能看出传递给函数的对象是否可以被函数修改。理论上来说,因为两个参数都是引用,mapTo()函数可以修改其中的任一个,但Qt Jambi不允许修改QPoint参数,因为在C++中QPoint是作为常量引用传递的。通常根据上下文信息可以清楚的判断出哪些参数可以改变哪些不能改变。如有疑问,可以查阅参考文档理清这种情况。

      除了在C++中那些作为常量值或常量引用传递的不可变参数外,Qt Jambi还保证了任何非void函数的返回值是一个独立的副本(在C++中函数返回值都是常量值或常量引用),因此改变函数返回值不会有任何限制。

      前面提到过,C++/Qt中任何用到QString的地方,在Qt Jambi中都用Java的String代替。这种对应关系同样适用于QChar类,在Qt Jambi中有两个Java的对应类:char和java.lang.Character。对于Qt的一些容器类也有类似的对应关系:QHash被替换为java.util.HashMap,QList和QVector被替换为java.util.List,QMap被替换为java.util.SortedMap。此外,QThread被替换为java.lang.Thread。

      Qt的模型/视图架构和数据库API使QVariant得到了广泛应用。因为所有的Java对象都继承自java.lang.Object,所以Java中并不需要这种类型,在所有的Qt Jambi的API中,QVariant被替换为java.lang.Object。QVariant提供的其他函数可以在com.trolltech.qt.QVariant中以静态函数的方式使用。

      我们已经结束了对Qt Jambi小程序的介绍,并讨论了很多Qt Jambi和C++/Qt在编程方便的概念上的差别。编译运行Qt Jambi应用程序与其他Java程序无异,但是要设置CLASSPATH环境变量指向Qt Jambi的安装路径。我们必须用Java编译器编译程序才能用Java解释器运行程序。比如:

exportCLASSPATH=$CLASSPATH:$HOME/qtjambi/qtjambi.jar:$PWD

javac FindDialog.java

java FindDialog

      这里,我们使用Bash shell设置CLASSPATH环境变量值;如果使用其他命令行解释器,其语法可能与此不同。CLASSPATH中包含了当前文件夹,这样编译器和解释器就可以自动找到FindDialog类了。在Mac OS X系统中,必须将命令行选项-XstartOnFirstThread分配给Java,以通过Apple的Java虚拟机处理线程相关事务。在Windows系统中,我们这样执行应用程序:

setCLASSPATH=%CLASSPATH%;%JAMBIPATH%\qtjambi.jar;%CD%

javac FindDialog.java

java FindDialog

      QtJambi也可以在IDE中使用。下节将介绍如何用著名的Eclipse IDE编辑、编译、测试Qt Jambi应用程序。


微信公众号:Qt开发社区(期待您的关注,扫下方二维码或搜索“Qt开发社区”或"Qtkfsq")

投 稿 邮 箱 :luxingcan@aliyun.com

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ GUI Programming with Qt4 Second Edition 之 附录C.1 Qt Jambi入门 的相关文章

  • QTableWidget::itemAt() 返回看似随机的项目

    我刚刚开始使用 Qt 所以请耐心等待 当我使用 QTableWidget gt getItemAt 时 它返回的项目与我使用 currentItemChanged 并单击同一项目时不同 我相信有必要使用 itemAt 因为我需要获取单击的任
  • 如何确定 QTextDocument 的高度?

    给定一个特定的宽度 我想找出一个的高度QTextDocument 换句话说 如果QTextEdit其中包含QTextDocument is w宽 最小高度是多少h为了完全显示文档而不需要滚动条 将 QTextDocument 对象的宽度设置
  • 如何使用 qmake 和 macdeployqt 缩小应用程序

    如何使用 qmake 和 macdeployqt 缩小应用程序 我已在项目 pro 文件中设置 QT core gui 并在生成的应用程序上运行 qmake 和 macdeployqt 问题是该程序捆绑了 QtNetwork QtScrip
  • Qt 4.5 - 发出信号是函数调用还是线程,它是否会阻塞?

    我不确定 Qt 4 5 中信号 槽机制的性质 当发出信号时 是阻塞函数调用还是线程 说这个 emit GrabLatestData proceed with latest data 在继续下一行之前 所有信号 槽链是否都会被解析 这取决于
  • PyQt:在运行时翻译模块字符串

    字符串在QObjects 在运行时翻译 如果翻译器发生变化 所有这些字符串都会刷新 但是 在模块级别声明的字符串甚至静态类属性都会在导入时进行翻译 我可以看到 3 种允许翻译模块字符串的方法 但其中没有一种让我完全满意 安装翻译器后导入模块
  • 如何找到文本光标的全局位置?

    我想执行一个QMenu http qt nokia com doc 4 0 qmenu html文本光标位置处的对象QPlainTextEdit http doc trolltech com main snapshot qplaintext
  • 如何将X11事件传递给QDialog

    目前 我正在尝试将系统 X11 事件 在 Linux 上 传递给我创建的对象 为此 我从 QApplication 中将 eventFilter 安装到了我的对象上 这是有效的 因为它获取应用程序的所有事件 但是我还需要传递对象 X11 事
  • Qt - 自定义小数点和千位分隔符

    如何将数字 双精度 转换为具有自定义小数点和千位分隔符的字符串 我见过 QLocale 但我不想选择本地化国家 地区 而是指定我自己的小数点和千位分隔符 Thanks Qt 不支持自定义区域设置 但仅处理组和小数点字符很简单 const Q
  • 如何在非 GUI 应用程序中使用 QWebPage

    我想用QWebPage在非 GUI Qt 应用程序中 我的意思是我根本不想与窗口服务器通信 不过 使用 QtGui 不是问题 QWebPage内部创建一些QWidget实例 因此 使用QCoreApplication不可能 当创建一个QAp
  • 如何使用 QT 设置 PATH 变量?

    如何使用 QT 4 8 获取和设置 PATH 变量 我知道我可以使用 STL 中的 getenv 获取 PATH 变量值 但不知道如何使用 STL 或任何基于 Qt 的方法设置它 如果 QT 有它的功能 我想了解并使用它 而不是去使用 Wi
  • 在pyside中设置应用程序名称

    我在 Windows 8 和 Qt 5 下使用 Qt Creator Designer 创建了一个应用程序 它开始如下 class Ui MainWindow object def setupUi self MainWindow MainW
  • PyQt - QTableView 不响应 dataChanged 信号?

    QSqlQueryModel是一个很棒的数据库模型 但它是只读的 所以我重写了它setData and flags 方法 现在 我可以编辑我的数据库表QTableView 但是当我发出一个 QTableView 时 它不会刷新自己dataC
  • Qt4 无法使用 CMake 编译

    我现在在 Linux 下使用 KDevelop for C 我想编译 Qt4 应用程序 但是当我这样做时 它给了我以下错误 我编译 cmake DCMAKE INSTALL PREFIX usr local DCMAKE BUILD TYP
  • 如何指定Qmake自动生成的资源文件?

    我有一个带有德语翻译的 Qt 项目 Translation de ts 自动编译成Translation de qm通过 Qmake TRANSLATIONS Translation de ts QMAKE EXTRA COMPILERS
  • 更改 QT 主窗口的标题字体

    我想知道如何更改 QT 主窗口的标题字体 请参阅随附的屏幕截图 我尝试更改样式表等 但它不起作用 我也尝试使用 C 发送消息 但这也有效 SendMessage form gt effectiveWinId WM SETFONT WPARA
  • 我可以取消选中组框中的一组 RadioBottom 吗?

    组 Box 内的单选底部将被视为一组底部 它们是互斥的 我怎样才能清理他们的检查状态 我有几件收音机底部 其中一件经过检查 我怎样才能 清洁 取消选中 所有收音机底部 setChecked 在组内不起作用 我尝试做以下事情但失败了 我的代码
  • 如何使用 QWebElement 设置 input(type="file") 的值?

    我正在尝试将照片上传到vk com https vk com using QtWebKit https qt project org doc qt 4 8 qtwebkit html模块 我面临的问题是无法正确填写input type fi
  • 如何在点击 Qtablewidget 单元格时获取放置在该单元格中的小部件的行号?

    我正在尝试的是当用户选择项目时获取 QcomboBox 的行号 虽然使用它很容易获得单元格的列和行 cellClicked int int 信号 但仅当单元格上没有小部件时才有效 那么如果单元格中放置了小部件 如何获取行号 Note 所有组
  • 当我尝试构建 Qt 4.7.1 静态库时,“找不到 -ljscore”

    我尝试从最新的源构建静态 Qt 库 但出现以下错误 usr bin ld cannot find ljscore collect2 ld returned 1 exit status 如何解决这个问题呢 这是 Qt 构建系统中自 4 7 0
  • 如何使 QImage 或 QPixmap 半透明 - 或者为什么 setAlphaChannel 过时?

    4 7 并喜欢在 qgraphicsview 上叠加两个图像 顶部的图像应是半透明的 以便能够透过它看到 最初 两个图像都是完全不透明的 我期望存在一些为每个像素设置全局 alpha 值的函数 但似乎没有这样的函数 最接近的是 QPixma

随机推荐

  • Pyspark实战(四)pyspark操作hbase

    环境配置 xff1a Spark 启动环境中添加 hbase 的 jar 包以及 spark examples的jar包 1 下载spark examples jar包 xff0c 地址https mvnrepository com art
  • 五、geotrellis实现栅格切片并存储至hbase

    部署环境可以参考本栏目的其他章节 1 maven代码如下 xff1a lt dependencies gt lt dependency gt lt groupId gt org apache camel lt groupId gt lt a
  • launch文件和package文件语法

    launch文件语法 参考 xff1a ROS入门之 浅谈launch 沐棋的博客 CSDN博客 roslaunch 补充 xff1a launch prefix 61 command prefix roslaunch 命令 的一个潜在的缺
  • ORB_SLAM2新增稠密建图代码笔记

    接上一篇博客 ORB SLAM2 43 kinect稠密建图实战项目总结 ORB SLAM2 43 kinect稠密建图实战项目总结 好好仔仔的博客 CSDN博客 本篇在此基础上对整个项目的逻辑结构以及代码实现进行梳理 orb slam2新
  • windows下C++学习推荐书籍

    推荐几本书给你们 xff0c 有空可以学习一下 xff1a C 43 43 编程相关 xff1a 1 C 43 43 Primer xff1a C 43 43 的工具书 2 Effective C 43 43 xff1a C 43 43 提
  • stm32IO口八种工作模式详细解析(附原理图)

    目录 工作模式介绍常用IO口工作模式分析实际应用 很多小伙伴们在初学stm32时都对stm32的IO口工作模式的原理和配置不了解 xff0c 所以我整理发表此篇文章作为自己复习和他人参考资料 xff08 注 xff1a 该文章参考了stm3
  • cmake之install总结(指定安装文件和安装位置)

    背景 cmake不仅可以构建可执行文件 xff0c 还可以安装 使用CMake xff0c 我们可以使用install 命令指定安装规则 只需要指定安装位置和待安装的目标文件 xff0c 十分简单 以cmake官方教程为例 xff08 3
  • 工训备赛日志(二)——上位机与stm32之间的一种简易通信方式

    工训备赛日志 xff08 二 xff09 上位机与stm32之间的一种简易通信方式 一 摘要 上位机检测到物体之后 xff0c 要将信号传递给控制底层的STM32 xff0c 这里提出了一种基于读取电平和外部中断的简易通信方式 此方法占用五
  • 【2】中断方式和查询方式的区别

    1 中断方式 xff1a 接收数据时 xff0c MCU转入中断服务程序 xff0c 再处理接收到的数据 xff1b CMT2300A接收数据的中断 xff1a 检测RX FIFO TH 中断 xff0c 一旦有效表示FIFO 已经被填入预
  • Ubantu 安装到VMware详解

    想要在VMware中运行Linux系统 xff0c 那么就需要Linux系统安装到VMware虚拟机上面 在这里 xff0c 以把ubantu16 04安装到VMware虚拟机中为教程进行图文讲解 xff0c 共分为三个步骤 xff0c 分
  • 数字直流电源设计

    设计目标 xff1a 市电输入 开关频率50KHz 60V 20A 1200W输出 输出电压纹波0 2 输出电流纹波20 效率0 8 1 确定输入电压 经查阅 xff0c 我国市电电压标准 xff0c 220V单相供电时 xff0c 为额定
  • CAN报文格式

    CAN协议的报文传输过程中有 数据帧 远程帧 错误帧 过载帧和帧间隔 nbsp nbsp nbsp nbsp nbsp nbsp nbsp 1 数据帧 用于发送节点向接收节点传送数据的帧 nbsp nbsp nbsp nbsp nbsp n
  • FreeRTOS调度器启动

    nbsp 在真正启动调度器之前 先创建空闲任务 初始化一些变量 真正启动调度器的函数是xPortStartScheduler 启动调度器 void vTaskStartScheduler void BaseType t xReturn if
  • 安装novnc,并加入开机自启

    1 安装git工具 apt get install git y 2 下载novnc git clone https github com novnc noVNC 3 ls 查看 xff0c 已经下载完成 4 vim novnc sh把启动命
  • 【C++初阶11-模版进阶】解锁C++模版更多玩法

    今天 xff0c 带来模版进阶的讲解 主要讲解 xff1a 非类型模版参数模版的特化模版的分离编译 文中不足错漏之处望请斧正 xff01 非类型模版参数 模版参数分为类型模版参数和非类型模版参数 可以这么理解 xff1a 前者是为了泛化类型
  • Qt 获取当前时间

    1 获取带日期的时间 xff0c 使用QDateTime类 QDateTime current date time 61 QDateTime currentDateTime QString current date 61 current d
  • Qt 判断文件或文件夹是否存在及创建文件夹

    1 判断文件夹是不是存在 参数说明 xff1a QString fullPath 文件夹全路径 方法1 bool isDirExist QString fullPath QDir dir fullPath if dir exists ret
  • Qt阻塞延时与非阻塞延时(四种方法之个人笔记)

    功能描述 毫秒级非阻塞延时函数 参数 延时毫秒数 其他说明 已试验 可用 但CPU占用率较高 void VdpuMngUI msecSleep int msec QTime dieTime 61 QTime currentTime addM
  • 获取本机所有网卡的网卡名、网卡描述、网卡MAC地址、网卡IP、网卡类型等信息及网线是否插入状态

    使用windows sdk提供的API函数GetAdaptersInfo 可以获得本机所有网卡的网卡名 网卡描述 网卡MAC地址 网卡IP 网卡类型等信息 xff0c 并用IP ADAPTER INFO结构体存储 xff0c 使用GetIf
  • C++ GUI Programming with Qt4 Second Edition 之 附录C.1 Qt Jambi入门

    Qt Jambi入门 本节 xff0c 我们将开发一个简单的Java应用程序并显示如图C 1所示的窗口 除窗口标题之外 xff0c Jambi Find对话框与第二章中创建的Find对话框的外观和功能均相同 通过使用相同的例子 xff0c