设计器的使用及常用控件
文章目录
一、设计器
1.设计器的使用
2.通过代码操作ui文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->pushButton->setText("text");
connect(ui->pushButton,&QPushButton,this,&MainWindow);
}
MainWindow::~MainWindow()
{
delete ui;
}
- 你可以把设计器中的所有功能理解为
ui->setupUi(this);
的功劳,所以如果想要在代码中修改ui界面,最好在这句代码之后。 - 而操作ui界面中控件的方式和操作普通控件的代码一样,只不过加了一个ui->前缀,代表是ui界面中的控件
二、设计器中的常用控件
1.Layouts:代表界面布局
2. Spacers:代表间距等
3. Buttons:按钮类
4. Item Views:数据库相关
5. Item Witgets:文件目录树相关
6. Containers:容器
7. Input Widgets:输出控件
8. Display Widgets:显示控件
9. QLabel控件
QLabel 是我们最常用的控件之一, 其功能很强大, 我们可以用来显示文本, 图片和动画等
- 显示文字 (普通文本、 html)
通过 QLabel 类的 setText 函数设置显示的内容:
voidsetText(const QString &)
- 可以显示普通文本字符串
QLable *label = new QLable;
label->setText(“Hello, World!”);
- 可以显示 HTML 格式的字符串
比如显示一个链接
QLabel * label = new QLabel(this);
label ->setText("Hello, World");
label ->setText("<h1><a href=\"https://www.baidu.com\">
百度一下</a></h1>");
label ->setOpenExternalLinks(true);
其中 setOpenExternalLinks()函数是用来设置用户点击链接之后是否自动打开
链接, 如果参数指定为 true 则会自动打开, 如果设置为 false, 想要打开链接
只 能 通 过 捕 捉 linkActivated() 信 号 , 在 自 定 义 的 槽 函 数 中 使 用QDesktopServices::openUrl()打开链接, 该函数参数默认值为 false
QLabel * label = new QLabel(this);
label ->setText("Hello, World");
label ->setText("<h1><a href=\"https://www.baidu.com\">
百度一下</a></h1>");
// label->setOpenExternalLinks(true);
connect(label, &QLabel::linkActivated,
this, &MyWidget::slotOpenUrl);
//槽函数
void MyWidget::slotOpenUrl(const QString &link)
{
QDesktopServices::openUrl(QUrl(link));
}
- 显示图片
可以使用 QLabel 的成员函数 setPixmap 设置图片
void setPixmap(const QPixmap &)
首先定义 QPixmap 对象
QPixmap pixmap;
然后加载图片
pixmap.load(":/Image/boat.jpg");
最后将图片设置到 QLabel 中
QLabel *label = new QLabel;
label.setPixmap(pixmap);
- 显示动画
可以使用 QLabel 的成员函数 setMovie 加载动画, 可以播放 gif 格式的文件
void setMovie(QMovie * movie)
首先定义 QMovied 对象, 并初始化:
QMovie *movie = new QMovie(":/Mario.gif");
播放加载的动画:
movie->start();
将动画设置到 QLabel 中:
QLabel *label = new QLabel;
label->setMovie(movie);
10.QLineEdit控件
Qt 提供的单行文本编辑框。
- 设置/获取内容
获取编辑框内容使用 text( ) , 函数声明如下:
QString text() const
设置编辑框内容
void setText(const QString &)
- 设置显示模式
使用 QLineEdit 类的 setEchoMode () 函数
设置文本的显示模式,函数声明:
void setEchoMode(EchoMode mode)
EchoMode 是一个枚举类型,一共定义了四种显示模式:
QLineEdit::Normal 模式显示方式, 按照输入的内容显示。
QLineEdit::NoEcho 不显示任何内容, 此模式下无法看到用户的输入
QLineEdit::Password 密码模式, 输入的字符会根据平台转换为特殊字符。
QLineEdit::PasswordEchoOnEdit 编辑时显示字符否则显示字符作为密码
另外, 我们再使用 QLineEdit 显示文本的时候, 希望在左侧留出一段空白的区域,
那么, 就可以使用 QLineEdit 给我们提供的 setTextMargins
函数:
void setTextMargins(int left, int top, int right, int bottom)
用此函数可以指定显示的文本与输入框上下左右边界的间隔的像素数。
- 设置输入提示
如果我们想实现一个与百度的搜索框类似的功能: 输入一个或几个字符, 下边会
列出几个跟输入的字符相匹配的字符串, QLineEdit 要实现这样的功能可以使用
该类的成员函数 setComleter()函数来实现:
voidsetCompleter(QCompleter * c)
创建 QCompleter 对象, 并初始化
QStringList tipList;
tipList<< “Hello” << “how are you” << “Haha” << “oh, hello”;
// 不区分大小写
completer->setCaseSensitivity(Qt::CaseInsensitive);
QCompleter *completer = new QCompleter(tipList, this);
QCompleter 类的 setCaseSensitivity()函数可以设置是否区分大小写, 它的参数是一个枚举类型:
Qt::CaseInsensitive 不区分大小写
Qt::CaseSensitive 区分大小写
如果不设置该属性, 默认匹配字符串时是区分大小写的
。
另外我们还可以设置字符串其中某一部分匹配, 此功能可通过 QCompleter 类的
setFilterMode 函数来实现,函数声明如下:
voidsetFilterMode(Qt::MatchFlags filterMode)
其参数为 Qt 定义的宏,有多重类型,具体可参考 Qt 帮助文档, 要实现我们上边提
到的功能, 参数可以使用 Qt::MatchContains
:
completer->setFilterMode(Qt::MatchContains);
属性设置完成之后, 将 QCompleter 对象设置到 QLineEdit 中:
QLineEdit *edit = new QLineEdit(this);
edit->setCompleter(completer);
11.布局管理器
所谓 GUI 界面, 归根结底, 就是一堆组件的叠加。 我们创建一个窗口, 把按钮
放上面, 把图标放上面, 这样就成了一个界面。 在放置时, 组件的位置尤其重要。
- 我们必须要指定组件放在哪里, 以便窗口能够按照我们需要的方式进行渲染。 这 就涉及到组件定位的机制。
- Qt 提供了两种组件定位机制:
绝对定位和布局定位
。 - 绝对定位就是一种最原始的定位方法: 给出这个组件的坐标和长宽值。这样, Qt 就知道该把组件放在哪里以及如何设置组件的大小。 但是这样做带来的一个问题是, 如果用户改变了窗口大小, 比如点击最大化按钮或者使用鼠标拖动窗口边缘, 采用绝对定位的组件是不会有任何响应的。 这也很自然, 因为你并没有告诉 Qt, 在窗口变化时, 组件是否要更新自己以及如何更新。 或者, 还有更简单的方法:
禁止用户改变窗口大小。 但这总不是长远之计。
- 布局定位: 你只要把组件放入某一种布局, 布局由专门的布局管理器进行管
理。 当需要调整大小或者位置的时候, Qt 使用对应的布局管理器进行调整。布局定位完美的解决了使用绝对定位的缺陷
Qt 提供的布局中以下三种是我们最常用的:
QHBoxLayout: 按照水平方向从左到右布局;
QVBoxLayout: 按照竖直方向从上到下布局;
QGridLayout: 在一个网格中进行布局, 类似于 HTML 的 table;
1. 水平/垂直/网格布局
下面我们通过一个例子来学习以下水平布局管理器的使用方法:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle("Enter your age");
QSpinBox *spinBox = new QSpinBox(&window);
QSlider *slider = new QSlider(Qt::Horizontal, &window);
spinBox->setRange(0, 130);
slider->setRange(0, 130);
QObject::connect(slider, &QSlider::valueChanged,
spinBox, &QSpinBox::setValue);
void (QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;
QObject::connect(spinBox, spinBoxSignal,
slider, &QSlider::setValue);
spinBox->setValue(35);
//给控件设置布局
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(spinBox);
layout->addWidget(slider);
window.setLayout(layout);
window.show();
return app.exec();
}
我们在这段代码中引入了两个新的组件: QSpinBox 和 QSlider。 QSpinBox 就是只能输入数字的输入框, 并且带有上下箭头的步进按钮。 QSlider 则是带有滑块的滑竿
上面的代码中 window.setLayout(layout); 是将布局设置到窗口 window 中, 在窗口中设置布局还有另一种写法:
//给控件设置布局
QHBoxLayout *layout = new QHBoxLayout(window) ;
layout->addWidget(spinBox);
layout->addWidget(slider);
在创建布局对象的时候给新对象指定父窗口, 就等于给传入的窗口设置了布局。另外布局与布局之间是可以嵌套使用的, 使用 addLayout() 方法。 QVBoxLayout的使用方法与 QHBoxLayout 完全相同
关于上述代码中信号和槽连接的解释
:
当数字输入框显示的内容发生改变的时候, 会发出一股信息, 滑块会接收这一信
号, 并作出改变。 如果二者的信号槽连接写成下边这样:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
编译器却会报错
no matching function for call to 'QObject::connect(QSpinBox*&,
<unresolved overloaded function type>, QSlider*&, void
(QAbstractSlider::*)(int))'
这是怎么回事呢? 从出错信息可以看出, 编译器认为 QSpinBox::valueChanged 是一个 overloaded 的函数
。 我们看一下 QSpinBox 的文档发现, QSpinBox 的确有两个信号:
void valueChanged(int)
void valueChanged(const QString &)
当我们使用&QSpinBox::valueChanged 取函数指针时, 编译器不知道应该取哪一个函数(记住前面我们介绍过的, signal 也是一个普通的函数。 ) 的地址, 因此报错。 解决的方法很简单, 编译器不是不能确定哪一个函数吗? 那么我们就显式指定一个函数。 方法就是, 我们创建一个函数指针, 这个函数指针参数指定为 int:
void (QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;
然后我们将这个函数指针作为 signal, 与 QSlider 的函数连接:
QObject::connect(spinBox, spinBoxSignal,
slider, &QSlider::setValue);
这样便避免了编译错误
2. 自定义控件
在搭建 Qt 窗口界面的时候, 在一个项目中很多窗口, 或者是窗口中的某个模块
会被经常性的重复使用。 一般遇到这种情况我们都会将这个窗口或者模块拿出来
做成一个独立的窗口类, 以备以后重复使用。在使用 Qt 的 ui 文件搭建界面的时候, 工具栏栏中只为我们提供了标准的窗口控件, 如果我们想使用自定义控件怎么办?
例如: 我们从 QWidget 派生出一个类 SmallWidget, 实现了一个自定窗口
// smallwidget.h
class SmallWidget : public QWidget
{
Q_OBJECT
public:
explicit SmallWidget(QWidget *parent = 0);
signals:
public slots:
private:
QSpinBox* spin;
QSlider* slider;
};
// smallwidget.cpp
SmallWidget::SmallWidget(QWidget *parent) : QWidget(parent)
{
spin = new QSpinBox(this);
slider = new QSlider(Qt::Horizontal, this);
// 创建布局对象
QHBoxLayout* layout = new QHBoxLayout;
// 将控件添加到布局中
layout->addWidget(spin);
layout->addWidget(slider);
// 将布局设置到窗口中
setLayout(layout);
// 添加消息响应
connect(spin,static_cast<void (QSpinBox::*)(int)>
(&QSpinBox::valueChanged),slider,
&QSlider::setValue);
connect(slider, &QSlider::valueChanged,spin, &QSpinBox::setValue);
}
那么这个 SmallWidget 可以作为独立的窗口显示,也可以作为一个控件来使用