QT入门

1. 信号与槽

  • [static]QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type=Qt::AutoConnection)
举例:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)));

需要注意:

  • 信号与槽函数参数要一致
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int)));//ok
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int)));//error
  • 可以带有缺省参数
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int=0)));//ok
  • 信号函数的参数可以多于槽函数,多余参数将被忽略
QObject::connect(A,SIGNAL(sigfun(int,int)),B,SLOT(slotfun(int)));//ok
  • 一个信号可以被连接到多个槽(一对多)
QObject::connect(A,SIGNAL(sigfun(int)),B1,SLOT(slotfun1(int)));//ok
QObject::connect(A,SIGNAL(sigfun(int)),B2,SLOT(slotfun2(int)));//ok
  • 多个信号也可以连接到同一个槽(多对一)
QObject::connect(A1,SIGNAL(sigfun1(int)),B,SLOT(slotfun(int)));//ok
QObject::connect(A2,SIGNAL(sigfun2(int)),B,SLOT(slotfun(int)));//ok
  • 两个信号可以直接连接(信号级联)
QObject::connect(A1,SIGNAL(sigfun1(int)),A2,SIGNAL(sigfun2(int)));//ok

题外话:connect的重载版本

QMetaObject::ConnectionQObject::connect(const QObject *sender,const char *signal, const QObject *receiver, const char *method,Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method,Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const char *method,Qt::ConnectionType type=Qt::AutoConnection) const
QMetaObject::Connection QObject::connect(const QObject *sender,PointerToMemberFunction signal,const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type =Qt::AutoConnection)
QMetaObject::Connection QObject::connect(const QObject *sender,PointerToMemberFunction signal,Functor functor)
QMetaObject::Connection QObject::connect(const QObject *sender,PointerToMemberFunction signal,const QObject*context,Functor functor,Qt::ConnectionType type=Qt::AutoConnection)

2. 常用界面设计组件

2.1窗体

窗体是指程序的整体界面,可以包含标题栏、菜单栏、工具栏、关闭按钮、最小化按钮、最大化按钮等。QMainWindow、QWidget、QDialog三个类就是用来创建窗体的,可以直接使用也可以继承后再使用。


  • QMainWindow
    QMainWindow窗口可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,可以作为GUI程序的主窗口。



    注意:若不显示菜单栏可按如下方式设置


  • QDialog
    QDialog是对话框窗口的基类。对话框主要用来执行短期任务,或与用户进行互动,它可以是模态的也可以是非模态的。
    QDialog没有菜单栏、工具栏、状态栏等。


  • QWidget
    QWidget是Qt中所有可绘制类的基类。任何基于QWidget的类都可以在没有父类的情况下显示为窗口。



    如果是主窗口,就使用QMainWindow;如果是对话框,就是用QDialog;如果不确定,或有可能作为顶级窗口,也有可能嵌入到其他窗口中,那么使用QWidget。

2.1.1设置窗体位置、大小及背景颜色

窗体初始位置为(100,100),控制窗体不可更改大,最大、最小均为800x640,背景色为红色。

MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(new Ui::MainWindow){
  ui->setupUi(this);
  //或者使用setGeometry
  move(100,100);
  setMaximumSize(800,640);
  setMinimumSize(800,640);
  setStyleSheet("background:red");
}
2.1.2设置窗体标题
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QIcon>
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){
  ui->setupUi(this);
  //或者使用setGeometry
  move(100,100);
  setMaximumSize(800,640);
  setMinimumSize(800,640);
  setStyleSheet("background:red");
  setWindowTitle("QT太棒了");
  setWindowIcon(QIcon(":/images/Qt.ico"));
}
MainWindow::~MainWindow(){
  delete ui;
}

2.2 字符串与输入输出组件

2.2.1 字符串与数值之间的转换

界面设计时使用最多的组件恐怕就是QLabel和QLineEdit了,QLabel用于显示字符串,QLineEdit用于显示和输入字符串。这两个类都有如下两个成员函数用于读取和设置显示文字。

QString text() const;
void setText(const QString &text);

这两个函数都涉及到了QString类。QString类是Qt程序中经常使用的类,用于处理字符串。QString类可以进行字符串与数字之间的转换,使用QLineEdit就可以实现数字量的输入输出。
下图为基于QWidget创建的可视化窗体。


#include"widget.h"
#include"ui_widget.h"
Widget::Widget(QWidget*parent):QWidget(parent),ui(new Ui::Widget){
  ui->setupUi(this);
}
Widget::~Widget(){
  delete ui;
}
void Widget::on_btnCalc_clicked(){
  QString text = ui->le_num->text();
  int num = text.toInt();
  text = ui->le_price->text();
  float price =text.toFloat();
  float sum = price *num;
  text = text.asprintf("%.2f",double(sum));
  ui->le_sum->setText(text);
}

小结:

  • 字符串转数字
int toInt(bool *ok = nullptr, int base = 10) const
long toLong(bool *ok = nullptr, int base = 10)const
short toShort(bool *ok = nullptr, int base = 10) const 
uint toUInt(bool *ok = nullptr,int base = 10) const 
ulong toULong(bool *ok = nullptr, int base = 10) const 
ushort toUShort(bool *ok = nullptr, int base = 10) const 
double toDouble(bool *ok = nullptr) const
float toFloat(bool *ok = nullptr) const
  • 数字转字符串
text = QString::number(double(sum),'f',2);
text= QString::asprintf("%.2f",double(sum));//重点记忆一种就可以了这个和C语法一致建议重点记忆
text = text.sprintf("%.2f",double(sum));
text = text.setNum(sum,'f',2);
2.2.2 QString的常用功能

QString提供了大量的功能,有助于灵活实现字符串处理功能,可以可以通过查看QT帮助手册得到。下面举几个例子。

  • append() 和 prepend()
  • toUpper() 和 toLower()
  • count()、size() 和 length()
/*
字符串中如果有汉字 每个汉字算一个字符
*/
text = "NI 好啊";
num = text.size();//5
  • trimmed() 和 simplified()
//Returns a string that has whitespace removed from the start and the end.
//This includes the ASCII characters '\t', '\n', '\v', '\f', '\r', and ' '.
QString str = " lots\t of\nwhitespace\r\n ";
str = str.trimmed();
//str = "lots\t of\nwhitespace"
/*Returns a string that has whitespace removed from the start and the end, and that has each sequence of internal whitespace replaced with a single space*/
QString str = " lots\t of\nwhitespace\r\n ";
str = str.simplified();//str = "lots of whitespace";
  • indexOf()和 lastIndexOf()
  • append() 和 arg()
QString i;
//current file's number QString total;
//number of files to process
QString fileName;
//current file'sname
QString status = QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);
  • section()
QString str;
QString csv = "forename,middlename,surname,phone";
QString path = "/usr/local/bin/myapp";//First field is empty
QString::SectionFlag flag = QString::SectionSkipEmpty;
str = csv.section(',', 2, 2);// str == "surname"
str = path.section('/',3 , 4);//str=="bin/myapp"
str = path.section('/',3,3,flag);//str=="myapp"
  • endsWith() 和 startsWith()
  • isNull() 和 isEmpty()

2.3 数字输入和显示组件

QSpinBox用于整数的显示和输入,一般显示十进制数,也可以显示二进制、十六进制数,而且可以在显示框中增加前缀或后缀。
QDoubleSpinBox用于浮点数的显示和输入,可以设置显示小数的位数,也可以设置显示前缀和后缀。



设计按钮对应的槽函数

void Widget::on_btnCalc_clicked()
{
  int num = ui->sb_num->value();
  double price = ui->dsb_price->value();
  double sum = num * price;
  ui->dsb_sum->setValue(sum);
}

可以在Designer中直接设置以下属性


2.3.2 其它数值输入和显示组件
  • QSlider
    QSlider 和 QDial 2个组件都从QAbstractSlider继承而来,有一些共有的属性。QSlider是滑动的标尺型组件,滑动标尺上的一个滑块可以改变值。


  • QDial
    QDial是仪表盘式的组件,通过旋转表盘获得输入值。特有的属性包括:


  • QProgressBar
    它的父类是QWidget,一般用于显示进度


  • QLCDNumber
    QLCDNumber是模拟LCD显示数字的组件,可以显示整数或小数。小数点也算一个数位。


创建基于QWidget的工程,如下图所示:


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QColor>
#include <QPalette>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->slider_red,SIGNAL(valueChanged(int)),this,SLOT(on_slider_valueChanged(int)));
    connect(ui->slider_green,SIGNAL(valueChanged(int)),this,SLOT(on_slider_valueChanged(int)));
    connect(ui->slider_blue,SIGNAL(valueChanged(int)),this,SLOT(on_slider_valueChanged(int)));
    connect(ui->slider_alpha,SIGNAL(valueChanged(int)),this,SLOT(on_slider_valueChanged(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_slider_valueChanged(int value)
{
    int red = ui->slider_red->value();
    int green = ui->slider_green->value();
    int blue = ui->slider_blue->value();
    int alpha = ui->slider_alpha->value();

    QColor color;
    color.setRgb(red,green,blue,alpha);

    QPalette pal = ui->textEdit->palette();
    pal.setColor(QPalette::Base,color);
    ui->textEdit->setPalette(pal);
}

2.4 按钮组件

QPushButton、QRadioButton、QCheckBox都从QAbstractButton,拥有一些共的属性,如下图所示:



图标使用setIcon()来设置,文本可以在构造函数或通过setText()来设置。可以使用isChecked()检查是否被选中。

  • QPushButton
    QPushButton是Qt常用的控件之一,提供普通的按钮功能。通过信号槽机制接收触发信号并执行对应动作。
  • QRadioButton
    单选框默认开启自动互斥(autoExclusive)。如果启用了自动互斥,属于同一个父部件的单选框的行为就和属于一个互斥按钮组的一样。如果你需要为属于同一父部件的单选框设置多个互斥按钮组,把它们加入QButtonGroup中。
  • QCheckBox
    它也是一个可选择的按钮,常见用途是在要求用户选择一个或多个可用选项的情况下。与单选按钮不同,默认情况下复选框不是互斥的。checkBox按钮可以通过在QButtonGroup对象中添加它们而互斥。每当选中或清除复选框时,它都会发出信号状态Changed()。如果要在每次复选框更改状态时触发操作,请连接到此信号。您可以使用isChecked()查询复选框是否被选中。
    注意:QCheckBox可以有两种状态,也可以有三种状态(未选中,选中,半选),默认是两种状态。


void MainWindow::on_btn_input_clicked()
{
    QString info = "我是:";
    if(ui->rb_male->isChecked()){
        info += "男生,";
    }else if(ui->rb_fmale->isChecked()){
        info += "女生,";
    }else{
        info += "性别不便透露";
    }

    info += "平时爱好:";
    if(ui->cb_read->isChecked()){
        info += ui->cb_read->text();
        info +=",";
    }
    if(ui->cb_grame->isChecked()){
        info += ui->cb_grame->text();
        info +=",";
    }
    if(ui->cb_cartoon->isChecked()){
        info += ui->cb_cartoon->text();
        info +=",";
    }
    if(ui->cb_swimming->isChecked()){
        info += ui->cb_swimming->text();
        info +=",";
    }
    if(ui->cb_basketball->isChecked()){
        info += ui->cb_basketball->text();
        info +=",";
    }

    int pos = info.lastIndexOf(",");
    info.replace(pos,1,".");

    ui->textBrowser->setText(info);
}


void MainWindow::on_btn_clear_clicked()
{
    ui->textBrowser->clear();
    ui->rb_male->setAutoExclusive(false);
    ui->rb_male->setChecked(false);
    ui->rb_male->setAutoExclusive(true);
    ui->rb_fmale->setAutoExclusive(false);
    ui->rb_fmale->setChecked(false);
    ui->rb_fmale->setAutoExclusive(true);

    ui->cb_read->setChecked(false);
    ui->cb_grame->setChecked(false);
    ui->cb_basketball->setChecked(false);
    ui->cb_cartoon->setChecked(false);
    ui->cb_swimming->setChecked(false);
}

2.5 布局组件

Qt的界面设计使用了布局(Layout)功能。所谓布局,就是界面上组件的排列方式,使用布局可以使组件有规则地分布,并且随着窗体大小变化自动地调整大小和相对位置。
Qt提供了QHBoxLayout类(水平排列布局),QVBoxLayout类(垂直排列布局),QGridLayout类(网格排列布局)等基本布局管理。
它们之间的继承关系如下图所示。


addWidget()方法用于向布局中加入组件。
addLayout()方法用于向布局中加入子布局。

2.6 容器组件

为了将界面上的各个组件的分布设计得更加美观,经常使用一些容器类,如QGoupBox、QTabWidget、QToolBox等。

2.6.1 QGroupBox
#ifndef WIDGET_H
#define WIDGET_H
#include<QWidget>
#include<QGroupBox>
#include<QRadioButton>
class Widget: publicQWidget
{
  Q_OBJECT
public:
  Widget(QWidget *parent =0);
  ~Widget();
private:
  QGroupBox *gb1;
  QGroupBox *gb2;
  QRadioButton *rb1;
  QRadioButton *rb2;
  QRadioButton *rb3;
  QRadioButton *rb4;
  QRadioButton*rb5;
};
#endif //WIDGET_H

#include "widget.h"
#include<QVBoxLayout>
#include<QHBoxLayout>
Widget::Widget(QWidget *parent):QWidget(parent)
{
  gb1 = new QGroupBox("性别",this);
  rb1 = new QRadioButton("男");
  rb2 = new QRadioButton("女");
  QVBoxLayout *vb1 = new QVBoxLayout();
  vb1->addWidget(rb1);
  vb1->addWidget(rb2);
  gb1->setLayout(vb1);
  gb2 = new QGroupBox("所在年级");
  rb3 = new QRadioButton("三年级");
  rb4 = new QRadioButton("四年级");
  rb5 = new QRadioButton("五年级");
  QVBoxLayout *vb2 = newQVBoxLayout;
  vb2->addWidget(rb3);
  vb2->addWidget(rb4);
  vb2->addWidget(rb5);
  gb2->setLayout(vb2);
  QHBoxLayout *mainLayout =new QHBoxLayout(this);
  mainLayout->addWidget(gb1);
  mainLayout->addWidget(gb2);
  setLayout(mainLayout);
}
Widget::~Widget()
{
}
2.6.2 QScrollArea
#ifndef WIDGET_H
#define WIDGET_H
#include<QWidget>
#include<QLabel>
#include<QScrollArea>
classWidget:public QWidget
{
Q_OBJECT
public:
  Widget(QWidget *parent = 0);
  ~Widget();
private:
  QLabel*lb;
  QScrollArea*sa;
}
;
#endif//WIDGET_H

#include"widget.h"
#include<QVBoxLayout>
Widget::Widget(QWidget*parent):QWidget(parent)
{
  lb = new QLabel(this);
  QPixmap pix("1.png");
  lb->setPixmap(pix);
  sa = new QScrollArea(this);
  sa->setWidget(lb);
  QVBoxLayout *mainbox = new QVBoxLayout;
  mainbox->addWidget(sa);
  this->setLayout(mainbox);
}
2.6.3 QToolBox

QToolBox类提供了一列选项卡窗口,当前项显示在当前选项卡下面,适用于分类浏览、内容展示、操作指引这一类的使用场景。


#include "widget.h"
#include <QPushButton>
#include<QToolBox>
#include<QHBoxLayout>
Widget::Widget(QWidget*parent):QWidget(parent)
{
  ui->setupUi(this);
  QToolBox*tb =new QToolBox(this);
  QWidget *page1 = new QWidget(this);
  QVBoxLayout *layout1 = newQVBoxLayout(this);
  QPushButton *pb1 = new QPushButton("大话西游",page1);
  QPushButton *pb2 = new QPushButton("功夫",page1);
  QPushButton *pb3 = new QPushButton("整蛊专家",page1);
  layout1->addWidget(pb1);
  layout1->addWidget(pb2);
  layout1->addWidget(pb3);
  page1->setLayout(layout1);
  tb->addItem(page1,"周星驰");
  QWidget *page2 = new QWidget(this);
  QVBoxLayout *layout2 = new QVBoxLayout(this);
  QPushButton *pb5 = new QPushButton("无间道",page2);
  QPushButton *pb6 = new QPushButton("拆弹专家",page2);
  layout2->addWidget(pb5);
  layout2->addWidget(pb6);
  page2->setLayout(layout2);
  tb->addItem(page2,"刘德华");
  QHBoxLayout *mainLayout = newQHBoxLayout;
  mainLayout->addWidget(tb);
  setLayout(mainLayout);
}
Widget::~Widget()
{
  delete ui;
}
2.6.4 QTabWidget

QTabWidget的一种带标签页的窗口,在这种类型的窗口中可以存储多个子窗口,每个子窗口的显示可以通过对应的标签进行切换。


#include"widget.h"
#include<QVBoxLayout>
Widget::Widget(QWidget*parent):QWidget(parent)
{
  tw = new QTabWidget;
  te1 = new QTextEdit("11111111");
  te2 = new QTextEdit("112221111");
  te3 = new QTextEdit("11113333");
  tw->addTab(te1,"1.c");
  tw->addTab(te2,"2.c");
  tw->addTab(te3,"3.c");
  QVBoxLayout*mainbox=new QVBoxLayout;
  mainbox->addWidget(tw);
  this->setLayout(mainbox);
}
Widget::~Widget()
{
}
2.6.5 QStackedWidget

QStackedWidget列提供了堆栈窗体的效果。在实际应用中,堆栈窗体多与列表框QlistWidget和下拉列表框QCombobox配合使用。


#include "widget.h"
#include <QVBoxLayout>
Widget::Widget(QWidget*parent):QWidget(parent)
{
  sw = new QStackedWidget;
  te1 = new QTextEdit("aaaa");
  te2 = new QTextEdit("aaadsfasdfasdfa");
  te3 = new QTextEdit("aaasdfaaa");
  sw->addWidget(te1);
  sw->addWidget(te2);
  sw->addWidget(te3);
  cb = new QComboBox;
  cb->addItem("1111");
  cb->addItem("2222");
  cb->addItem("3333");
  QVBoxLayout *mainbox = new QVBoxLayout;
  mainbox->addWidget(sw);
  mainbox->addWidget(cb);
  this->setLayout(mainbox);
  connect(cb,SIGNAL(activated(int)),sw,SLOT(setCurrentIndex(int)));
}
Widget::~Widget()
{
}

2.7 时间日期与定时器

2.7.1 时间日期相关的类

时间日期是经常遇到的数据类型,Qt中时间日期类型的类如下:
QTime,时间数据类型,仅表示时间,如18:08:08。
QDate,日期数据类型,仅表示日期,如2023-7-21。
QDateTime,日期时间数据类型,表示日期和时间,如2023-07-21 18:08:08。
QT中有专门用于日期、时间编辑和显示的界面组件,如下:QTimeEdit,编辑显示时间的组件。
QDateEdit,编辑和显示日期的组件。
QDateTimeEdit,编辑和显示日期时间的组件。
QCalendarWidget,一个用日历形式选择日期日期的组件。定时器是用来处理周期性事件的一种对象,类似于硬件定时器。例如设置一个定时器的定时周期为1000毫秒,那么每1000毫秒就会发射定时器的timeout()信号,在信号关联的槽函数里就可以做相应的处理。
Qt中的定时器类为QTimer,它直接从QObject类继承而来,不是界面组件类。

2.7.2 日期时间数据与字符串之间的转换

QDateEdit和QTimeEdit都从QDateTimeEdit继承而来,实现针对日期或时间的特定显示功能。实际上QDateEdit和QTimeEdit的显示功能都可以通过QDateTimeEdit实现,只需要设置好属性即可。


时间日期转字符串的函数:

QString QDateTime::toString(constQString &format)const

设置“读取当前日期时间”按钮对应的槽函数

#include "widget.h"
#include "ui_widget.h"
#include<QDateTime>
Widget::Widget(QWidget*parent):QWidget(parent),ui(new Ui::Widget)
{
  ui->setupUi(this);
}
Widget::~Widget()
{
  delete ui;
}
void Widget::on_btnGetTime_clicked()
{
  //获取当期日期时间
  QDateTime curDateTime = QDateTime::currentDateTime();
  ui->timeEdit->setTime(curDateTime.time());
  ui->editTime->setText(curDateTime.toString("hh:mm:ss"));
  ui->dateEdit->setDate(curDateTime.date());
  ui->editDate->setText(curDateTime.toString("yyyy-MM-dd"));
  ui->dateTimeEdit->setDateTime(curDateTime);
  ui->editDateTIme->setText(curDateTime.toString("yyyy-MM-dd hh:mm:ss"));
}

字符串转时间日期的函数:

QDateTime QDateTime::fromString(constQString &string, constQString &format)
void Widget::on_btnSetDateTime_clicked()
{
  QString str = ui->editDateTime->text();
  str = str.trimmed();
  if(!str.isEmpty()){
    QDateTime datetime =mQDateTime:: fromString(str,"yyyy年MM月dd日hh:mm:ss");
    ui->dateTimeEdit->setDateTime(datetime);
  }
}
2.7.3 QCalendarWidget日历组件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  connect(ui->calendarWidget,SIGNAL(selectionChanged()),this,SLOT(on_calendar_changed()));
}
MainWindow::~MainWindow()
{
  delete ui;
}
void MainWindow::on_calendar_changed(){
  QDate date = ui->calendarWidget->selectedDate();
  ui->editDate->setText(date.toString("yyyy-MM-dd"));
}
2.7.4 定时器

Qt中的定时器类是QTimer。QTimer不是一个可见的界面组件,在UI设计器的组件面板里找不到它。QTimer主要的属性是interval,是定时中断的周期,单位是毫秒。QTimer主要的信号是timeout(),在定时中断时发射此信号,要想在定时中断里做出响应,这就需要编写timeout()信号的槽函数。
QElapsedTimer用于快速计算两个事件的间隔时间,它没有父类,不支持Qt的元对象系统,QElapsedTimer的主要接口函数定义如下:

void start()//复位并启动计时器
qint64  elapsed()//返回流逝的时间,单位:毫秒
qint64 nsecsElapsed()//返回流逝的时间,单位:纳秒
qint64 restart()//重新启动计时器
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QTimer>
#include<QElapsedTimer>
namespace Ui
{
  class MainWindow;
}
class MainWindow:publicQMainWindow
{
  Q_OBJECT
public:
  explicit MainWindow(QWidget *parent =nullptr);
  ~MainWindow();
private:
  Ui::MainWindow*ui;
  QTimer timer;
  QElapsedTimer  counter;
private slots:
  void on_timeout();
  void on_btnStart_clicked();
  void on_btnStop_clicked();
  void on_sbInter_valueChanged(const QString &arg1);
};
#endif//MAINWINDOW_H


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  timer.setInterval(ui->sbInter->value());
  bool flag = connect(&timer, SIGNAL(timeout()), this,SLOT(on_timeout()));
  if(flag){
    qDebug()<<"successed";
  }else{
    qDebug()<<"failed";
  }
}
MainWindow::~MainWindow()
{
  delete ui;
}
voidMainWindow::on_timeout(){
  QTime curTime = QTime::currentTime();
  ui->LCDH->display(curTime.hour());
  ui->LCDM->display(curTime.minute());
  ui->LCDS->display(curTime.second());
}
void MainWindow::on_btnStart_clicked()
{
  timer.start();
  counter.start();
  ui->btnStart->setEnabled(false);
  ui->btnStop->setEnabled(true);
  ui->sbInter->setEnabled(false);
}
void MainWindow::on_btnStop_clicked()
{
  timer.stop();
  int msec =counter.elapsed();
  int ms = msec%1000;
  int sec = msec/1000;
  QString text = QString::asprintf("%d秒,%d毫秒",sec,ms);
  ui->letimes->setText(text);
  ui->btnStop->setEnabled(false);
  ui->btnStart->setEnabled(true);
  ui->sbInter->setEnabled(true);
}
void MainWindow::on_sbInter_valueChanged(constQString&arg1)
{
  timer.setInterval(arg1.section('',0,0).toInt());
}

3. 对话框与多窗体设计

一个完整的应用程序设计中,不可避免地会涉及多个窗体、对框框的设计和调用,如何设计和调用这些对话框和窗体是搞清楚 一个庞大的应用程序设计的基础。本章将介绍对话框和多窗体设计、调用方式、数据传递等问题。

3.1 标准对话框

Qt为应用程序设计提供了一些常用的标准对话框,如打开文件对话框、选择颜色对话框、信息提示和确认选择对话框、标准输入对话框等,用户无需再自己设计这些常用的对话框,这样可以减少程序设计工作量。

3.1.1 QFileDialog对话框


选择打开一个文件
若要打开一个文件,可调用静态函数

QString QFileDialog::getOpenFileName()
//example
//该函数返回用户选择的文件名称,若用户取消返回null
//父窗口,窗口标题,初始目录,文件过滤器
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"/home",tr("Images(*.png*.xpm*.jpg)"));
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include<QFileDialog>
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
}
MainWindow::~MainWindow()
{
  delete ui;
}
void MainWindow::on_pushButton_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle = "选择一个文件";
  QString filter = "文本文件(*.txt);;图片文件(*.jpg*.gif);;所有文件(*.*)";
  QString aFileName = QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
  if(!aFileName.isEmpty()){
    ui->plainTextEdit->appendPlainText(aFileName);
  }
}

选择打开多个文件

QStringList QFileDialog::getOpenFileNames()
//example
QStringList files = QFileDialog::getOpenFileNames(this,"Select one or more files to open","/home","Images(*.png*.xpm*.jpg)");
void MainWindow::on_btn_select_files_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle = "选择多个文件";
  QString filter = "文本文件(*.txt);;图片文件(*.jpg*.gif);;所有文件(*.*)";
  QStringList files = QFileDialog::getOpenFileNames(this,dlgTitle,curPath,filter);
  for(int i =0;i<files.count();i++){
    ui->plainTextEdit->appendPlainText(files.at(i));
  }
}

选择已有目录

QString QFileDialog::getExistingDirectory()
//example
QString dir = QFileDialog::getExistingDirectory(this,tr("OpenDirectory"),"/home",QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);
void MainWindow::on_btn_select_dir_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle = "选择目录";
  QString dirName = QFileDialog::getExistingDirectory(this,dlgTitle,curPath,QFileDialog::ShowDirsOnly);
  if(!dirName.isEmpty()){
    ui->plainTextEdit->appendPlainText(dirName);
  }
}

选择保存文件名

QString QFileDialog::getSaveFileName()
//example
QString fileName = QFileDialog::getSaveFileName(this,tr("SaveFile"),"/home/jana/untitled.png",tr("Imges(*.png*.xpm*.jpg)"));
void MainWindow::on_btn_save_file_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle = "保存文件";
  QString filter ="h文件(*.h);;C++文件(*.cpp);;所有文件(*.*)";
  QString filename = QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
  if(!filename.isEmpty()){
    ui->plainTextEdit->appendPlainText(filename);
  }
}
3.1.2 QColorDialog对话框
QColor QColorDialog::getColor(constQColor &initial = Qt::white,QWidget *parent = nullptr,const QString &title = QString(), QColorDialog::ColorDialogOptions options = ...)
voidMainWindow::on_btn_set_color_clicked()
{
  QPalette pal = ui->plainTextEdit->palette();
  QColor initColor = pal.color(QPalette::Text);
  //现有文字的颜色
  QColor color = QColorDialog::getColor(initColor,this,"选择颜色");
  if(color.isValid()){
    pal.setColor(QPalette::Text,color);
    ui->plainTextEdit->setPalette(pal);
  }
}
3.1.3 QFontDialog对话框
QFont QFontDialog::getFont(bool*ok,const QFont &initial,QWidget*parent = nullptr,const QString
&title = QString(),QFontDialog::FontDialogOptions options =...)
//example
bool ok;
QFont font = QFontDialog::getFont(&ok,QFont("Times",12),this);
if(ok)
{
//font is set to the font the userselected
}else{
//the user canceled the dialog; font is set to the initial
//value,in this case Times,12.
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QFileDialog>
#include<QStringList>
#include<QPalette>
#include<QColorDialog>
#include<QFontDialog>
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
}
MainWindow::~MainWindow()
{
  delete ui;
}
void MainWindow::on_pushButton_clicked()
{
   QString curPath = QDir::currentPath();
  QString dlgTitle = "选择一个文件";
  QString filter = "文本文件(*.txt);;图片文件(*.jpg*.gif);;所有文件(*.*)";
  QString aFileName = QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
  if(!aFileName.isEmpty()){
    ui->plainTextEdit->appendPlainText(aFileName);
  }
}

void MainWindow::on_btn_select_files_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "选择多个文件";
QString filter = "文本文件(*.txt);;图片文件(*.jpg*.gif);;所有文件(*.*)";
QStringList files = QFileDialog::getOpenFileNames(this,dlgTitle,curPath,filter);
for(int i =0; i<files.count();i++){
ui->plainTextEdit->appendPlainText(files.at(i));
}
}
void MainWindow::on_btn_select_dir_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle ="选择目录";
  QString dirName = QFileDialog::getExistingDirectory(this,dlgTitle,curPath, QFileDialog::ShowDirsOnly);
  if(!dirName.isEmpty()){
    ui->plainTextEdit->appendPlainText(dirName);
  }
}
void MainWindow::on_btn_save_file_clicked()
{
  QString curPath = QDir::currentPath();
  QString dlgTitle = "保存文件";
  QString filter = "h文件(*.h);;C++文件(*.cpp);;所有文件(*.*)";
  QString filename = QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
  if(!filename.isEmpty()){
    ui->plainTextEdit->appendPlainText(filename);
  }
}
void MainWindow::on_btn_set_color_clicked()
{
  QPalette pal = ui->plainTextEdit->palette();
  QColor initColor = pal.color(QPalette::Text);
  //现有文字的颜色
  QColor color = QColorDialog::getColor(initColor,this,"选择颜色");
  if(color.isValid()){
    pal.setColor(QPalette::Text,color);
    ui->plainTextEdit->setPalette(pal);
  }
}
void MainWindow::on_btn_set_font_clicked()
{
  QFont initFont = ui->plainTextEdit->font();
  bool ok = false;
  QFont font = QFontDialog::getFont(&ok,initFont);
  if(ok){
    ui->plainTextEdit->setFont(font);
  }
}
3.1.4 QInputDialog标准输入对话框

QInputDialog有单行字符串输入、整数输入、浮点数输入、列表框选择和多行文本等多种输入方式。
文字输入



#include"mainwindow.h"
#include"ui_mainwindow.h"
#include<QLineEdit>
#include<QInputDialog>
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
}
MainWindow::~MainWindow()
{
  delete ui;
}
void MainWindow::on_btn_input_string_clicked()
{
  QString dlgTitle = "输入文字对话框";
  QString  txtLabel = "请输入文件名";
  QString defaultInput ="新建文件.txt";
  QLineEdit::EchoMode echoMode = QLineEdit::Normal;
  bool ok =false;
  QString text =   QInputDialog::getText(this,dlgTitle,txtLabel,echoMode,defaultInput,&ok);
  if(ok&&!text.isEmpty()){
    ui->plainTextEdit->appendPlainText(text);
  }
}

输入整数


void MainWindow::on_btn_input_int_clicked()
{
  QString dlgTitle ="输入整数对话框";
  QString txtLabel ="设置字体大小";
  int defaultVal =ui->plainTextEdit->font().pointSize();
  int minVal =6, maxVal =50,stepVal=1;
  bool ok =false;
  int   inputVal=QInputDialog::getInt(this,dlgTitle,txtLabel,defaultVal,minVal,maxVal,stepVal,&ok);
  if(ok){
    QFont font =ui->plainTextEdit->font();
    font.setPixelSize(inputVal);
    ui->plainTextEdit->setFont(font);
  }
}

输入浮点数


void MainWindow::on_btn_input_double_clicked()
{
  QString dlgTitle = "输入浮点数对话框";
  QString txtLabel = "输入一个浮点数";
  double defaultVal=3.14;
  doublemminVal =0,maxVal=10000;
  int decimals= 2;
  bool ok =false;
  double inputVal =QInputDialog::getDouble(this,dlgTitle,txtLabel,defaultVal,minVal,maxVal,decimals,&ok);
  if(ok){
    QString str =QString::asprintf("输入了一个浮点数:%.2f",inputVal);
    ui->plainTextEdit->appendPlainText(str);
  }
}

下拉列表选择输入


void MainWindow::on_btn_input_listitem_clicked()
{
  QStringList items;
  items<<"优秀"<<"良好"<<"合格"<<"不及格";
  QString dlgTitle ="条目选择对话框";
  QString txtLabel = "请选择级别";
  int curIndex =0;
  //初始选择项
  bool editable =true;
  //列表框是否可编辑
  bool ok =false;
  QString text =QInputDialog::getItem(this,dlgTitle,txtLabel,items,curIndex,editable,&ok);
  if(ok&&!text.isEmpty()){
    ui->plainTextEdit->appendPlainText(text);
  }
}

4.文件操作

文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处理而开发的,所以文件读写是应用程序开发的一个基本功能。
注意:从物理上讲,文本文件与二进制文件本质上是没有区别的,都是以二进制形式保存在磁盘中。Windows系统中,文本文件读写时存在\r \n和\n的替换问题(写时\n会被替换为\r \n,读出时\r \n会被替换为\n)。
二进制文件读写时没有任何替换。Linux系统中,文本文件与二进制文件没有区别。

4.1 文本文件读写

文本文件是以纯文本格式存储的文件,例如大家编程实现的.c .h .cpp文件。HTML和XML文件也是纯文本文件,只是读取之后需要对内容进行解析之后再显示。Qt提供了两种读写纯文本文件的基本方法,一种是用QFile类的IODevice读写功能直接进行读写,另一种是利用QFile和QTextStream结合起来,用流(stream)的方法进行读写。

4.1.1QFile读写文本文件

QFile类是直接与IO设备打交道,进行文件读写操作的类,使用QFile可以直接打开或保存文本文件。



open文件

bool QFile::open(QIODevice::OpenMode mode)
bool QFile::open(FILE*fh,QIODevice::OpenMode mode,QFileDevice::FileHandleFlags handleFlags = DontCloseHandle)
bool QFile::open(int fd,QIODevice::OpenMode mode,QFileDevice::FileHandleFlags handleFlags =DontCloseHandle)
QIODevice::OpenMode,常用取值
QIODevice::ReadOnly 
QIODevice::WriteOnly
QIODevice::ReadWrite
QIODevice::Append
QIODevice::Truncate
QIODevice::Text
QFileDevice::FileHandleFlags
QFileDevice::AutoCloseHandle
//QFile.close()后自动关闭文件句柄
QFileDevice::DontCloseHandle
//QFile.close()后不关闭文件句柄
//example
QFile file1("a.txt");
file1.open(QIODevice::ReadOnly|QIODevice::Text);
QFile file2;
file2.open(stderr,QIODevice::WriteOnly|QIODevice::Text);
//stderr定义在stdio.h中
QFilefile3;
file3.open(STDERR_FILENO,QIODevice::WriteOnly|QIODevice::
Text);//STDERR_FILENO定义在unistd.h中

读操作

qint64 QIODevice::read(char*data,qint64maxSize);
QByteArray QIODevice::read(qint64 maxSize);
QByteArray QIODevice::readAll()
qint64QIODevice::readLine(char*data,qint64maxSize)
QByteArray QIODevice::readLine(qint64maxSize=0)

写操作:

qint64 QIODevice::write(const char*data,qint64maxSize);
qint64 QIODevice::write(const char*data);
qint64 QIODevice::write(constQByteArray &byteArray)
#include"mainwindow.h"
#include"ui_mainwindow.h"
#include<QDir>
#include<QFileDialog>
#include<QFile>
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
  ui->setupUi(this);
}
MainWindow::~MainWindow()
{
  delete ui;
}
void MainWindow::on_pushButton_clicked(){
  QString aFileName = QFileDialog::getOpenFileName(this,"打开一个文件",QDir::currentPath(),"程序文件(*.h*.cpp*.c);;文本文件(*.txt);;所有文件(*.*)");
  if(aFileName.isEmpty()){
    return;
  }
  QFile aFile(aFileName);
  if(!aFile.exists()){
    return;
  }
  if(!aFile.open(QIODevice::ReadOnly|QIODevice::Text)){
    return;
  }
  //ui->plainTextEdit->setPlainText(aFile.readAll());
  while(!aFile.atEnd()){
    QByteArray line=aFile.readLine();
    ui->plainTextEdit->appendPlainText(line);
  }
  aFile.close();
}
void MainWindow::on_btn_save_clicked()
{
  QString aFileName = QFileDialog::getSaveFileName(this,"另存为",QDir::currentPath(),"程序文件(*.h*.cpp*.c);;文本文件(*.txt);;所有文件(*.*)");
  if(aFileName.isEmpty()){
    return;
  }
  QFile aFile(aFileName);
  if(!aFile.open(QIODevice::WriteOnly|QIODevice::Text)){
    return;
  }
  QString str =ui->plainTextEdit->toPlainText();
  QByteArray strBytes=str.toUtf8();
  //转换为字节数组
  aFile.write(strBytes,strBytes.length());
  aFile.close();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.1 介绍 Qt:它是一套基于C++的跨平台开发框架,包括GUI、字符串、多线程处理、文件IO、网络IO、3D渲...
    hywing阅读 877评论 0 1
  • 第一部分概述 第一次建立helloworld程序时,曾看到Qt Creator提供的默认基类只有QMainWind...
    你的社交帐号昵阅读 3,885评论 0 6
  • 界面 主窗口界面设计 标题栏:直接设Window-Title属性;Window-icon属性可加图标。底部状态栏:...
    码园老农阅读 3,971评论 1 13
  • QT学习笔记 1.对象树:在Qt中,每个 QObject 内部都有一个list,用来保存所有的 children,...
    油炸花生米1阅读 860评论 0 1
  • (在b站学习QT,顺便做做笔记 2019年最新QT从入门到实战完整版|传智播客) 1.显示窗口; myWidget...
    冰糖葫芦多加冰阅读 1,196评论 0 1

友情链接更多精彩内容