ZT:使用Qt Style Sheet(1)

转自:http://hi.baidu.com/buptyoyo/blog/item/1ef4fd00d6e026054bfb5104.html

借用css 的灵感, Qt也支持Qt自己的css, 简称qss。同css 相似,qss的主要功能与最目的都是能使界面的表现与界面的元素分离,即质与形的分离,就如同一个人可以在不同的时候穿上不同的衣服一样,css机制的引入,使得设计一种皮肤与界面控件分离的软件成为可能,应用程序也能像web界面那样随意地改变外观。

1, QSS语法

css一样,他也有由一个selector与一个declaration组成,selector指定了是对哪一个控件产生效果,而declaration才是真正的产生作用的语句。如:

   QPushButton { color: red }

QPushButton指定了是对所有的QPushButton或是其子类控件(如用户定义的MyPushButton)产生影响,而color:red表明所有的受影响控件的前景色都为red

除了“类名”,“对象名”,“Qt属性名”这三样东西是大小写敏感的外其他的东西都是大小写不敏感的,如colorColor代表同一属性。

如果有几个selector指定了相同的declaration, 可以使用逗号(,)将各个选择器分开,如:

   QPushButton, QLineEdit, QComboBox { color: red }

他相当于:

   QPushButton { color: red }
QLineEdit { color: red }
 QComboBox { color: red }

declaration部份是一系列的(属性:值)对,使用分号(;)将各个不同的属性值对分开,使用大括号({})将所有declaration包含在一起。

1, 一般选择器(selector

Qt支持所有的CSS2定义的选择器,其祥细内容可以在w3c的网站上查找http://www.w3.org/TR/CSS2/selector.html 其中比较常用的selector类型有:

i. 通用类型选择器:*

会对所有控件有效果。

ii. 类型选择器:QPushButton

匹配所有QPushButton的实例和其子类的实例。

iii. 属性选择器:QPushButton[flat=”false”]

匹配所有QPushButton属性flatfalse的实例,属性分为两种,静态的和动态的,静态属性可以通过Q_PROPERTY() 来指定,来动态属性可以使用setProperty来指定,如:

QLineEdit *nameEdit = new QLineEdit(this);
nameEdit->setProperty("mandatoryField", true);

如果在设置了qssQt属性改变了,需要重新设置qss来使其生效,可以使用先unsetset qss

iv. 类选择器:.QPushButton

匹配所有QPushButton的实例,但不包含其子类,这相当于:

*[class~="QPushButton"]

~=的意思是测试一个QStringList类型的属性是否包含给定的QString。

v. ID选择器:QPushButton#okButton

对应Qt里面的object name设置,使用这条CSS之前要先设置对应控件的object nameokButton,如:

Ok->setObjectName(tr(“okButton”));

vi. 后裔选择器:QDialog QPushButton

匹配所有为QDialog后裔(包含儿子,与儿子的儿子的递归)为QPushButton的实例

vii. 子选择器:QDialog > QPushButton

匹配所有的QDialog直接子类QPushButton的实例,不包含儿子的儿子的递归。

2, 子控件选择器

i. 对于复杂的控件,可能会在其中包含其他子控件,如一个QComboxBox中有一个drop-down的按钮。那么现在如果要设置QComboxBox的下拉按钮的话,就可以这样访问:

   QComboBox::drop-down { image: url(dropdown.png) }

其标志是(::

ii. 子控件选择器是用位置的引用来代表一个元素,这个元素可以是一个单一控件或是另一个包含子控件的复合控件。使用subcontrol-origin属性可以改变子控件的默认放置位置,如:

QComboBox {
   margin-right: 20px;
 }
 QComboBox::drop-down {
   subcontrol-origin: margin;
 }

如上语句可以用来改变drop-downmargin

iii. 相对位置属性可以用来改变子控件相对于最初位置的偏移量,如当一个QComboxdrop-down按钮被按下时,我们可以用一个内部的小偏移量来表示被按下的效果,如下:

QComboBox::down-arrow {
   image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
   position: relative;
   top: 1px; left: 1px;
}

iv. 绝对位置属性允许子控件改变自己的位置和大小而不受引用元素的控件。一但位置被设定了,这些子控件就可以被当成一般的widget来对待,并且可以使用合模型。关于合模型可以参考下面。

如果你要查看Qt支持哪些子控件选择器,可以参考:

http://pepper.troll.no/s60prereleases/doc/stylesheet-reference.html#list-of-sub-controls

-syntax.html

3, 伪选择器(pseudo-states

i. 伪选择器以冒号(:)表示,与css里的伪选择器相似,是基于控件的一些基本状态来限定程序的规则,如hover规则表示鼠标经过控件时的状态,而press表示按下按钮时的状态。如:

QPushButton:hover {

Background-color:red;

}

表示鼠标经过时QPushButton背景变红。

ii. Pseudo还支持否定符号(!),如:

  QRadioButton:!hover { color: red }

表示没有鼠标移上QRadioButton时他显示的颜色是red

iii. Pseudo可以被串连在一起,比如:

  QPushButton:hover:!pressed { color: blue; }

表示QPushButton在鼠标移上却没有点击时显示blue字,但如果点击的时候就不会显示blue颜色了。

iv. 同样可以和之前所讲的子控件选择器一起联合使用,如:

QSpinBox::down-button:hover { image: url(btn-combobox-press.bmp) }

v. 与前面所讲的一样,伪选择器,子控件选择器等都是可以用逗号(,)分隔表示连续相同的设置的,如:

QPushButton:hover,QSpinBox::down-button, QCheckBox:checked { color: white ;image: url(btn-combobox-press.bmp);} 表示如下

vi. 更多请参考:

http://pepper.troll.no/s60prereleases/doc/stylesheet-reference.html#list-of-pseudo-states

D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'D:\Qt\ZT_Modbus\ZTCommTable\ZtModbusOta.cpp:-1: error: undefined reference to `vtable for OTAThread'
最新发布
03-22
<think>嗯,用户遇到了QT项目中的“undefined reference to vtable for OTAThread”错误。我需要先回忆一下这个错误的常见原因。通常这种错误和虚函数表相关,可能是在类中有虚函数但没有正确实现,或者析构函数的问题。 首先,用户提到的OTAThread类可能继承自QObject或者QThread,并且包含了一些虚函数。根据引用[2]的内容,没有用virtual修饰析构函数可能导致这个问题。所以应该检查OTAThread的析构函数是否声明为virtual,并且是否有实现。如果析构函数只有声明而没有定义,链接时就会找不到符号,导致虚表不完整。 其次,用户可能没有在类声明中使用Q_OBJECT宏。这个宏对于Qt的信号槽机制是必须的,而且它也会处理一些元对象系统的代码生成。如果遗漏了这个宏,moc工具就不会生成相应的元对象代码,从而导致虚表错误。这时候需要清理项目,重新运行qmake和构建,确保moc处理正确。 另外,检查是否所有的虚函数都有实现。比如,如果OTAThread重写了QThread的run()方法,但忘记提供实现,也会导致类似的错误。需要确保每个虚函数都有对应的函数体,即使是空的实现。 引用[2]中还提到,进行qmake和重新构建的步骤。有时候构建系统可能会缓存旧的元对象信息,导致新添加的Q_OBJECT宏没有被处理。因此,建议用户先执行qmake,再清理并重新构建项目,确保所有步骤都正确执行。 还有可能的问题包括类定义在头文件中没有正确包含,或者链接时没有将生成的moc文件包含进去。需要确认OTAThread的头文件被正确包含在项目中,并且moc生成的cpp文件被编译和链接。 总结下来,可能的解决步骤是:检查Q_OBJECT宏是否存在,确保虚析构函数正确声明和定义,实现所有虚函数,执行qmake和重新构建。此外,注意代码中的拼写错误或者作用域问题,比如类名是否正确,命名空间是否恰当等。</think>### 问题分析 QT项目中出现`undefined reference to vtable for OTAThread`错误,通常与虚函数表(vtable)未正确生成有关。以下是逐步解决方案: --- ### 1. **确保类中声明了`Q_OBJECT`宏** - **原因**:若类继承自`QObject`或其子类(如`QThread`),且包含信号/槽或需要元对象系统支持,必须添加`Q_OBJECT`宏。缺少此宏会导致moc工具无法生成虚函数表。 - **解决方法**: ```cpp class OTAThread : public QThread { Q_OBJECT // 必须添加 public: // ... }; ``` --- ### 2. **检查虚析构函数是否实现** - **原因**:若类中声明了虚函数(包括析构函数),但未实现,会导致虚函数表不完整[^2]。 - **解决方法**: ```cpp // 头文件声明 class OTAThread : public QThread { Q_OBJECT public: explicit OTAThread(QObject *parent = nullptr); virtual ~OTAThread(); // 必须声明为virtual }; // 源文件实现 OTAThread::~OTAThread() { // 析构逻辑(可为空) } ``` --- ### 3. **执行qmake并重新构建** - **原因**:修改头文件后需重新生成moc文件,否则虚函数表未被更新[^2]。 - **步骤**: 1. 点击Qt Creator菜单栏的 **【构建】→【执行qmake】**。 2. 点击 **【构建】→【清理项目】**。 3. 重新构建项目。 --- ### 4. **检查虚函数是否全部实现** - **原因**:若声明了虚函数但未实现,例如`run()`方法,会导致链接错误。 - **示例**: ```cpp class OTAThread : public QThread { Q_OBJECT protected: virtual void run() override; // 必须实现 }; // 源文件实现 void OTAThread::run() { // 线程逻辑 } ``` --- ### 5. **验证头文件包含与继承关系** - **原因**:若类未正确继承`QObject`或头文件未包含,会导致元对象系统失效。 - **示例**: ```cpp #include <QThread> // 确保包含基类头文件 class OTAThread : public QThread { // 正确继承 // ... }; ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值