当前位置: 首页 > article >正文

控件【QT】

文章目录

  • 控件
  • QWidget
    • enabled
    • geometry
    • setGeometry
  • qrc
  • windowOpacity
  • QPixmap
  • font
  • toolTip
  • focusPolicy
  • styleSheet
  • QPushButton
  • Radio Buttion
  • Check Box
  • 显示类控件

控件

Qt中已经提供了很多内置的控件了(按钮,文本框,单选按钮,复选按钮,下拉框…)

Qt中的各种控件都是继承自Qwidget类

QWidget

enabled

API :

isEnabled() , 获取到控件的可用状态

setEnabled , 设置控件是否可使用, true表示可用,false表示禁用.

enabled : 描述了一个控件是否处于“可用”状态.

所谓“禁用”指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。如果一个 widget 被禁用,则该 widget 的子元素也被禁用

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void  handle() ;
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton * button = new QPushButton(this) ;
    button->setText("按钮");
    //将按钮设置为禁用状态
    button->setEnabled(false) ;
    //禁用和是否连接槽函数无关
    connect(button, &QPushButton::clicked ,this , &Widget::handle);

}

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

void Widget::handle()
{
    qDebug() <<"handle";
}


切换第一个按钮的禁用状态

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_enable_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

//槽函数
void Widget::on_pushButton_clicked()
{
       qDebug() <<"执行了槽函数";
}

void Widget::on_pushButton_enable_clicked()
{
    //切换第一个按钮的禁用状态
  bool enable=   ui->pushButton->isEnabled();
  if(enable == true)
  {
       ui->pushButton->setEnabled(false) ;
  }
  else
  {
      //禁用
      ui->pushButton->setEnabled(true) ;
  }
}

geometry

API:

geometry ,获取到控件的位置和尺寸.返回结果是一个QRect,包含了x, y, width, height.其中x, y是左上角的坐标.

geometry视为是四个属性(x,y,width,height)的统称

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

geometry(),获取到控件的位置和尺寸.返回结果是一个QRect,包含了x, y, width, height.其中x, y是左上角的坐标.

例如:

setGeometry

move只是修改位置

setGeometry既可以修改位置,又可以修改尺寸

setGeometry(QRect) , 设置控件的位置和尺寸。可以直接设置一个QRect,也可以分四个属性单独设置。
setGeometry(int x, int y, int width, int height)

例如 : 平移一个按钮

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
   // void on_pushButton_clicked();


    void on_pushButton_up_clicked();

    void on_pushButton_down_clicked();



    void on_pushButton_left_clicked();

    void on_pushButton_right_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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


void Widget::on_pushButton_up_clicked()
{
    //获取target本身的geometry
             QRect rect     =  ui->pushButton_target->geometry();
            qDebug() <<rect ;
//            //将y-5
//            rect.setY(rect.y() -5);
//             ui->pushButton_target->setGeometry(rect);


             //平移
               ui->pushButton_target->setGeometry(rect.x() , rect.y()-5 ,rect.width(),rect.height() );

}

void Widget::on_pushButton_down_clicked()
{
    //获取target本身的geometry
             QRect rect     =  ui->pushButton_target->geometry();
            qDebug() <<rect ;
//            //将y-5
//            rect.setY(rect.y() +5);
//            ui->pushButton_target->setGeometry(rect);



            //平移
              ui->pushButton_target->setGeometry(rect.x() , rect.y()+5 ,rect.width(),rect.height() );
}

void Widget::on_pushButton_left_clicked()
{
    //获取target本身的geometry
             QRect rect     =  ui->pushButton_target->geometry();
            qDebug() <<rect ;
//            //将x-5
//            rect.setX(rect.x() -5);
//            ui->pushButton_target->setGeometry(rect);


            //平移
              ui->pushButton_target->setGeometry(rect.x()-5 , rect.y() ,rect.width(),rect.height() );


}

void Widget::on_pushButton_right_clicked()
{
    //获取target本身的geometry
             QRect rect     =  ui->pushButton_target->geometry();
            qDebug() <<rect ;
//            //将x+5
//            rect.setX(rect.x() +5);
//            ui->pushButton_target->setGeometry(rect);

            //平移
              ui->pushButton_target->setGeometry(rect.x()+5 , rect.y() ,rect.width(),rect.height() );
}

label 的使用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

widget.h :

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_accepted_clicked();

    void on_pushButton_reject_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp :

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    srand(time(nullptr));
}

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


void Widget::on_pushButton_accepted_clicked()
{
        ui->label->setText("是");

}

//鼠标点击后触发
void Widget::on_pushButton_reject_clicked()
{


}


//鼠标按下就触发
void Widget::on_pushButton_reject_pressed()
{
    ui->label->setText("否");

    //获取到当前程序窗口的尺寸
      int  width =this->geometry().width();
      int  height =  this->geometry().height();
    //重新生成按钮的位置
     int x = rand()%width;
      int y = rand()%height;
    //移动按钮的位置
      ui->pushButton_reject->move(x,y);
}


window frame:

如果 widget 作为一个窗口(带有标题栏,最小化,最大化,关闭按钮),那么在计算尺寸和坐标的时候就有两种算法,包含 window frame 和不包含 window frame。 其中 x(), y(), frameGeometry(), pos(), move() setFrameGeometry()都是按照包含 window frame 的方式来计算的。

其中 geometry(), width(), height(), rect(), size() setGeometry() 则是按照不包含 window frame 的方式来计算的。 当然,如果一个不是作为窗口的 widget,上述两类方式得到的结果是一致的

例如:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);



   QPushButton * mybutton = new QPushButton(this) ;
   mybutton->setText("按钮");
   mybutton->move(100,100) ;
   connect(mybutton , &QPushButton::clicked ,this , &Widget::handle );

}

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

void Widget::handle()
{
    QRect  rect1 =  this->geometry();
    QRect  rect2 =  this->frameGeometry();
    qDebug() <<rect1;
     qDebug() <<rect2;
}


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void handle () ;
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

API :

windowTitle () ,获取到控件的窗口标题

setWindowTitle (const Qstring& title) , 设置控件的窗口标题

windowTitle属性,只能针对顶层窗口这样的QWidget才有效

例如:

widget.cpp:

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("这是窗口标题");
     QPushButton * button = new QPushButton(this) ;
     button->setText("按钮");

}

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

API:

windowlcon : 获取到控件的窗口图标.返囱Qlcon对象

setWindowlcon(const Qlcon& icon) 设置控件的窗口图标.

这两个 api类似于windowTitle只能针对顶层窗口使用

例如:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QIcon>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置图标
    //通过绝对路径访问
    QIcon icon("D:/rose/rose-flower-pictures-beautiful-roses-love-rose-flower-beautiful-flowers-wallpapers-ai-generated-free-photo.jpg") ;
    this->setWindowIcon(icon) ;

}

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


qrc

qrc机制:

给 Qt 项目引入一个额外的 xml 文件(后缀名使用 .qrc 表示)
在这个 xml 中把要使用的图片资源给导入进来,并且在 xml 中进行记录。
Qt 在编译项目的时候,就会根据 qrc 中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转成 C++ 代码,最终编译到 .exe 里。

qrc 缺点:无法导入太大的资源文件

qrc机制,解决两个问题:

  1. 确保你的图片所在的路径在目标用户机器上存在。
  2. 确保你的图片不会被用户搞没了

qrc使用方式

1.在项目中创建一个qrc 文件,文件名不要带中文和特殊符号.

2把图片导入到qrc文件中

2.1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将prefix的前缀改成/即可

2.2 把刚才使用rose.jpg这个图片给导入到资源文件中.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:导入图片时,需要确保导入的图片必须在resource.qrc 文件的同级目录,或者同级目录中的子目录

把需要的图片拷贝到resource.qrc 文件的同级目录,或者同级目录中的子目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

当代码中需要访问qrc 中管理的文件时,就需要在路径上带有:前缀

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QIcon>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置图标
    //访问qrc
    //前缀 + 文件名 ,前缀就是:
    QIcon icon(":rose/rose.jpg") ;
    this->setWindowIcon(icon) ;

}

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




外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

windowOpacity

windowOpacity() , 获取到控件的不透明数值.返回float,取值为0.0 ->1.0其中0.0表示全透明,1.0表示完全不透明

setWindowOpacity(float n) , 设置控件的不透明值

例如;

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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


void Widget::on_pushButton_add_clicked()
{
    //增加透明度
    float opacity =this->windowOpacity();
    if(opacity >=1.0)
    {
        return ;
    }
    opacity += 0.1;
    this->setWindowOpacity(opacity) ;
}

void Widget::on_pushButton_sub_clicked()
{
    //减少透明度
    float opacity =this->windowOpacity();
    if(opacity <=0.0)
    {
        return ;
    }
    opacity -= 0.1;
    this->setWindowOpacity(opacity) ;
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_add_clicked();

    void on_pushButton_sub_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

2.7 cursor

API说明
cursor()获取到当前 widget 的 cursor 属性,返回 QCursor 对象。当鼠标悬停在该 widget 上时,就会显示出对应的形状。
setCursor(const QCursor& cursor)设置该 widget 光标的形状,仅在鼠标停留在该 widget 上时生效。
QGuiApplication::setOverrideCursor(const QCursor& cursor)设置全局光标的形状,对整个程序中的所有 widget 都会生效,覆盖上面的 setCursor 设置的内容。

setOverrideCursor: 设置全局光标(程序内的全局,而不是系统级别的全局

cursor() ,setCursor()widget级别的,一个界面中,不同的控件可以设成不同的光标

代码示例:在 Qt Designer 中设置按钮的光标

  1. 在界面中创建一个按钮

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QCursor>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QCursor cursor (Qt::WaitCursor) ;
    ui->pushButton->setCursor(cursor) ;
    // this->setCursor(cursor);
}

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


QPixmap

Qt允许我们通过自定义的图片来设置光标

QPixmap通过这个对象就表示一个图片

1、先准备一个图片,把图导入到项目中(qrc管理)
2、代码中访问到这个图片,基于这个图片构造出光标对象并设置

例如:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPixmap>
#include<QCursor>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //访问图片中文件
    QPixmap pixmap (":/dragon.jpg");
    //构造光标对象
    QCursor cursor(pixmap ,10,10) ;

    //设置光标
    this->setCursor(cursor) ;
}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

font

API说明
font()获取当前 widget 的字体信息,返回 QFont 对象。
setFont(const QFont& font)设置当前 widget 的字体信息。

关于 QFont

属性说明
family字体家族,比如 “楷体”, “宋体”, “微软雅黑” 等。
pointSize字体大小。
weight字体粗细,以数值方式表示粗细程度,取值范围为 [0, 99],数值越大,越粗。
bold是否加粗。设置为 true,相当于 weight 为 75。设置为 false 相当于 weight 为 50。
italic是否倾斜。
underline是否带有下划线。
strikeOut是否带有删除线。

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QLabel>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QLabel * label = new QLabel(this) ;
    label->setText("文本");

    //创建字体对象
    QFont font;
    font.setFamily("仿宋");
    font.setPixelSize(30) ;
    font.setBold(true) ;

     font.setItalic(true) ;
      font.setUnderline(true) ;
       font.setStrikeOut(true) ;

       //把font 对象设置到label中
       label->setFont(font) ;

}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

toolTip

2.9 toolTip

API说明
setToolTip设置提示内容。鼠标悬停在该 widget 上时会有提示说明。
setToolTipDuration设置 toolTip 提示的时间,单位 ms。时间到后 toolTip 自动消失。

toolTip 只是给用户看的,在代码中一般不需要获取到 toolTip。

代码示例:设置按钮的 toolTip

  1. 在界面上拖放两个按钮,objectName 设置为 pushButton_yes 和 pushButton_no

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();



private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->pushButton_yes->setToolTip("这是一个yes按钮");
      ui->pushButton_yes->setToolTipDuration(3000);
      ui->pushButton_no->setToolTip("这是一个no按钮");
        ui->pushButton_no->setToolTipDuration(7000);
}

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



focusPolicy

设置控件获取到焦点的策略。比如某个控件能否用鼠标选中或者能否通过tab键选中

所谓“焦点”,指的就是能选中这个元素。接下来的操作(比如键盘操作),就都是针对该焦点元素进行的了。这个对于输入框,单选框,复选框等控件非常有用。

—般来说一个控件获取到焦点,主要是两种方式

1.鼠标点击
2.键盘的tab

API说明
focusPolicy()获取该 widget 的 focusPolicy,返回 Qt::FocusPolicy
setFocusPolicy(Qt::FocusPolicy policy)设置 widget 的 focusPolicy。

Qt::FocusPolicy 是一个枚举类型,取值如下:

  • Qt::NoFocus:控件不会接收键盘焦点
  • Qt::TabFocus:控件可以通过 Tab 键接收焦点
  • Qt::ClickFocus:控件在鼠标点击时接收焦点
  • Qt::StrongFocus:控件可以通过 Tab 键和鼠标点击接收焦点(默认值)
  • Qt::WheelFocus:类似于 Qt::StrongFocus,同时控件也通过鼠标滚轮获取到焦点(新增的选项,一般很少使用)。

代码示例:理解不同的 focusPolicy

  1. 在界面上创建四个单行输入框(Line Edit)

styleSheet

通过 CSS 设置 widget 的样式。

CSS (Cascading Style Sheets 层叠样式表) 本身属于网页前端技术,主要就是用来描述界面的样式。所谓 “样式”,包括不限于大小、位置、颜色、间距、字体、背景、边框等。我们平时看到的丰富多彩的网页,就都会用到大量的 CSS。

Qt 虽然是做 GUI 开发,但实际上和网页前端有很多异曲同工之处。因此 Qt 也引入了对于 CSS 的支持。

CSS 中可以设置的样式属性非常多,基于这些属性 Qt 只能支持其中一部分,称为 QSS (Qt Style Sheet)。具体的支持情况可以参考 Qt 文档中 “Qt Style Sheets Reference” 章节。

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPlainTextEdit>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

}

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


void Widget::on_pushButton_light_clicked()
{
    // 设置窗口的样式
  this->setStyleSheet("background-color: rgb(240,240,240);");
    // 设置输入框的样式
    ui->plainTextEdit->setStyleSheet("background-color: white; color: black;");
    // 设置按钮的样式
    ui->pushButton_light->setStyleSheet("color: black;");
    ui->pushButton_dark->setStyleSheet("color: black;");
}

void Widget::on_pushButton_dark_clicked()
{
    // 设置窗口的样式
    this->setStyleSheet("background-color: black;");
    // 设置输入框的样式
    ui->plainTextEdit->setStyleSheet("background-color: black; color: white;");
    // 设置按钮的样式
    ui->pushButton_light->setStyleSheet("color: white;");
    ui->pushButton_dark->setStyleSheet("color: white;");
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_light_clicked();

    void on_pushButton_dark_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

QPushButton

属性说明
text按钮中的文本
icon按钮中的图标
iconSize按钮中图标的尺寸
shortCut按钮对应的快捷键
autoRepeat按钮是否会重复触发。当鼠标左键按住不放时,如果设为true,则会持续产生鼠标点击事件;如果设为false,则必须释放鼠标,再次按下鼠标时才能产生点击事件。(相当于游戏手柄上的"连发"效果)
autoRepeatDelay重复触发的延时时间。按住按钮多久之后,开始重复触发。
autoRepeatInterval重复触发的周期。

给按钮设置图标

1 、 使用qrc添加图片

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //创建图标对象
    QIcon icon(":/doge.png");

    //设置图标
    ui->pushButton->setIcon(icon) ;
    //设置图标尺寸
     ui->pushButton->setIconSize(QSize(50,50)) ;
}

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

实现带有快捷键的按钮

1、创建qrc 文件,导入资源

2、编辑ui文件,创建界面

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置这些按钮的图标
    ui->pushButton_target->setIcon(QIcon(":/image/doge.png"));

    ui->pushButton_target->setIconSize(QSize(120, 120));

    ui->pushButton_up->setIcon(QIcon(":/image/up.png"));
    ui->pushButton_up->setIconSize(QSize(50, 50));

    ui->pushButton_down->setIcon(QIcon(":/image/down.png"));
    ui->pushButton_down->setIconSize(QSize(50, 50));

    ui->pushButton_left->setIcon(QIcon(":/image/left.png"));
    ui->pushButton_left->setIconSize(QSize(50, 50));

    ui->pushButton_right->setIcon(QIcon(":/image/right.png"));
    ui->pushButton_right->setIconSize(QSize(50, 50));

//    //第一种写法设置快捷键

//    ui->pushButton_up->setShortcut(QKeySequence("w"));
//    ui->pushButton_down->setShortcut(QKeySequence("s"));
//    ui->pushButton_left->setShortcut(QKeySequence("a"));
//    ui->pushButton_right->setShortcut(QKeySequence("d"));



    //第二种写法(推荐): 还可以通过按键的枚举来设置按键快捷键。
    ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));
    ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_S));
    ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));
    ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));
    
    //组合键
    //ui->pushButton_up->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_W));
}

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


void Widget::on_pushButton_up_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5,rect.width(), rect.height());
}

void Widget::on_pushButton_down_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5,rect.width(), rect.height());
}


void Widget::on_pushButton_right_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x() +5, rect.y() ,rect.width(), rect.height());
}


void Widget::on_pushButton_left_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x() -5, rect.y() ,rect.width(), rect.height());
}


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_up_clicked();

    void on_pushButton_left_clicked();

    void on_pushButton_right_clicked();

    void on_pushButton_down_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

自动连发

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置这些按钮的图标
    ui->pushButton_target->setIcon(QIcon(":/image/doge.png"));

    ui->pushButton_target->setIconSize(QSize(120, 120));

    ui->pushButton_up->setIcon(QIcon(":/image/up.png"));
    ui->pushButton_up->setIconSize(QSize(50, 50));

    ui->pushButton_down->setIcon(QIcon(":/image/down.png"));
    ui->pushButton_down->setIconSize(QSize(50, 50));

    ui->pushButton_left->setIcon(QIcon(":/image/left.png"));
    ui->pushButton_left->setIconSize(QSize(50, 50));

    ui->pushButton_right->setIcon(QIcon(":/image/right.png"));
    ui->pushButton_right->setIconSize(QSize(50, 50));

//    //第一种写法设置快捷键

//    ui->pushButton_up->setShortcut(QKeySequence("w"));
//    ui->pushButton_down->setShortcut(QKeySequence("s"));
//    ui->pushButton_left->setShortcut(QKeySequence("a"));
//    ui->pushButton_right->setShortcut(QKeySequence("d"));



    //第二种写法(推荐): 还可以通过按键的枚举来设置按键快捷键。
   // ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));
    ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_S));
    ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));
    ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));

    //组合键
    ui->pushButton_up->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_W));




    // 开启鼠标点击的连发功能(键盘的连发默认就是支持的)
    ui->pushButton_up->setAutoRepeat(true);
    ui->pushButton_down->setAutoRepeat(true);
    ui->pushButton_left->setAutoRepeat(true);
    ui->pushButton_right->setAutoRepeat(true);
}

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


void Widget::on_pushButton_up_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5,rect.width(), rect.height());
}

void Widget::on_pushButton_down_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5,rect.width(), rect.height());
}


void Widget::on_pushButton_right_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x() +5, rect.y() ,rect.width(), rect.height());
}


void Widget::on_pushButton_left_clicked()
{
    //获取target的位置
  QRect rect = ui->pushButton_target->geometry();

    //修改位置
    ui->pushButton_target->setGeometry(rect.x() -5, rect.y() ,rect.width(), rect.height());
}


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_up_clicked();

    void on_pushButton_left_clicked();

    void on_pushButton_right_clicked();

    void on_pushButton_down_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

Radio Buttion

QRadioButton 是单选按钮 作为QAbstractButton 和 QWidget 的⼦类, 上⾯介绍的属性和⽤法,对于QRadioButton
同样适⽤

属性说明
checkable是否能选中
checked是否已经被选中。checkable 是 checked 的前提条件。
autoExclusive是否排他。选中一个按钮之后是否会取消其他按钮的选中。对于 QRadioButton 来说默认就是排他的。

例如:

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->radioButton_male->setChecked(true) ;
    ui->label->setText("您选择的性别为:其他");
       ui->radioButton_other->setChecked(false) ;


//        //禁用其他选项,setCheckable只是能够让按钮不被选中.仍然是可以响应点击事件
//       ui->radioButton_other->setCheckable(false) ;

//        //第一种写法:
//       ui->radioButton_other->setEnabled(false) ;


               //第二种写法:
              ui->radioButton_other->setCheckable(false) ;
              ui->radioButton_other->setDisabled(true);

}

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


void Widget::on_radioButton_male_clicked()
{
    //把界面上的 label 的内容进行更新
     ui->label->setText("您选择的性别为:男");
}

void Widget::on_radioButton_female_clicked()
{
    //把界面上的 label 的内容进行更新
     ui->label->setText("您选择的性别为:女");
}

void Widget::on_radioButton_other_clicked()
{
    //把界面上的 label 的内容进行更新
     ui->label->setText("您选择的性别为:其他");
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_radioButton_male_clicked();

    void on_radioButton_female_clicked();

    void on_radioButton_other_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

• clicked 是⼀次⿏标按下+⿏标释放触发的.
• pressed 是⿏标按下触发的.
• released 是⿏标释放触发的.
• toggled 是 checked 属性改变时触发的
总的来说,toggled是最适合 QRadioButton 的

例如:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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


void Widget::on_radioButton_clicked(bool checked)
{
    //此处从checked就表示了当前radioButton的选中状态.
            qDebug() << "clicked: " << checked;

}



void Widget::on_radioButton_2_pressed()
{
      qDebug() << "pressed: " ;
}

void Widget::on_radioButton_3_released()
{
     qDebug() << "released: " ;
}

void Widget::on_radioButton_4_toggled(bool checked)
{
  // checked 状态发生改变,就会触发这个信号
            qDebug() << "toggled: " << checked;

}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_radioButton_clicked(bool checked);



    void on_radioButton_2_pressed();

    void on_radioButton_3_released();

    void on_radioButton_4_toggled(bool checked);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

每⼀组内部来控制排他, 但是组和组之间不能排他

例如:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QButtonGroup>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //使用 QButtonGroup对单选按钮进行分组
    QButtonGroup* group1 = new QButtonGroup(this);
    QButtonGroup* group2 = new QButtonGroup(this);
    QButtonGroup* group3 = new QButtonGroup(this);

    // 把上述单选按钮,放到不同的组里。
    group1->addButton(ui->radioButton);
    group1->addButton(ui->radioButton_2);
    group1->addButton(ui->radioButton_3);

    group2->addButton(ui->radioButton_4);
    group2->addButton(ui->radioButton_5);
    group2->addButton(ui->radioButton_6);

    group3->addButton(ui->radioButton_7);
    group3->addButton(ui->radioButton_8);
}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

Check Box

QCheckBox 表⽰复选按钮.

可以允许选中多个和QCheckBox 最相关的属性也是 checkable 和 checked ,都是继承⾃QAbstractButton .
⾄于 QCheckBox 独有的属性 tristate ⽤来实现 “三态复选框”

在界⾯上创建?三个复选按钮,?和⼀个普通按钮

例如:

widget.cpp

#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_pushButton_clicked()
{
    QString result = "今天你的安排是:";
    if (ui->checkBox_study->isChecked()) {
        result += ui->checkBox_study->text() + " ";
    }
    if (ui->checkBox_game->isChecked()) {
        result += ui->checkBox_game->text() + " ";
    }
    if (ui->checkBox_work->isChecked()) {
        result += ui->checkBox_work->text();
    }
    ui->label->setText(result);
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

显示类控件

QLabel 可以⽤来显⽰⽂本和图⽚
核⼼属性如下

  • textQLabel 中的文本。
  • textFormat:文本的格式。
    • Qt::PlainText:纯文本。
    • Qt::RichText:富文本(支持 HTML 标签)。
    • Qt::MarkdownText:Markdown 格式。
    • Qt::AutoText:根据文本内容自动决定文本格式。
  • pixmapQLabel 内部包含的图片。
  • scaledContents:设为 true 表示内容自动拉伸填充 QLabel,设为 false 则不会自动拉伸。
  • alignment:对齐方式。可以设置水平和垂直方向如何对齐。
  • wordWrap:设为 true 内部的文本会自动换行,设为 false 则内部文本不会自动换行。
  • indent:设置文本缩进,水平和垂直方向都生效。
  • margin:内部文本和边框之间的边距。不同于 indentmargin 是上下左右四个方向都同时有效,而 indent 最多只是两个方向有效(具体哪两个方向有效取决于 alignment)。
  • openExternalLinks:是否允许打开一个外部的链接。(当 QLabel 文本内容包含 URL 的时候涉及到)
  • buddy:给 QLabel 关联一个“伙伴”,这样点击 QLabel 时就能激活对应的伙伴。例如伙伴如果是一个 QCheckBox,那么该 QCheckBox 就会被选中。

widget.cpp:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //纯文本
    ui->label->setTextFormat(Qt::PlainText) ;
    ui->label->setText("<b>这是一段纯文本<b>") ;
    //富文本

    ui->label_2->setTextFormat(Qt::RichText) ;
    //  <b> 标签:让文本加粗
    ui->label_2->setText("<b>这是一段富文本</b>") ;

    //markdown 文本


    ui->label_3->setTextFormat(Qt::MarkdownText) ;
    ui->label_3->setText("#这是一段markdown文本") ;
}

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



widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

标签加到纯文本中,只是被当成了单纯的文本没有进行任何的渲染操作

在纯文本中,#只是被单纯的当成了"文本"

在markdown中,#则是一级标题了

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //将QLabel 设置成和窗口一样大,并且把这个 QLabel左上角设置到窗口的左上角这里
    QRect windowRect = this->geometry();
    ui->label->setGeometry(0,0,windowRect.width(), windowRect.height());
    QPixmap pixmap( ":/dragon.jpg");
    ui->label->setPixmap(pixmap ) ;
    //将qrc图片与窗口大小保持一致
    ui->label->setScaledContents(true) ;
}

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

在上面代码中是在构造函数里,进行的尺寸设置,这个尺寸设置相当于是"一次性的"

一旦程序运行起来之后,QLabel的尺寸就固定下来了.窗口发生改变,此时,QLabel是不会变化的

如果需要将图片与窗口实现同步拉伸:

解决方案:

可以让 Widget窗口类,重写父类(QWidget)的resizeEvent虚函数

widget.cpp

让Widget窗口类,重写父类(QWidget)的resizeEvent虚函数

在鼠标拖动窗口尺寸中,在这个过程中 ,resizeEvent函数会被反复调用执行

每次触发一个resizeEvent事件都会调用一次对应的虚函数

因为进行了函数重写,调用父类的虚函数就会调用子类对应的函数

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QResizeEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //将QLabel 设置成和窗口一样大,并且把这个 QLabel左上角设置到窗口的左上角这里
    QRect windowRect = this->geometry();
    ui->label->setGeometry(0,0,windowRect.width(), windowRect.height());
    QPixmap pixmap( ":/dragon.jpg");
    ui->label->setPixmap(pixmap ) ;
    //将qrc图片与窗口大小保持一致
    ui->label->setScaledContents(true) ;
}

Widget::~Widget()
{
    delete ui;
}
//重写父类(QWidget)的resizeEvent虚函数,将图片与窗口实现同步拉伸

//此处的形参event,包含了触发这个resize事件这一时刻,窗口的尺寸的数值
void Widget::resizeEvent(QResizeEvent *event)
{
    //qDebug() <<event->size() ;
    ui->label->setGeometry(0,0,event->size().width(), event->size().height());
}


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void resizeEvent(QResizeEvent * event);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

事件:

用户的操作,会对应一些信号,Qt中,表示用户的操作,有两类概念,一个是信号,另一个是事件

当用户拖拽修改窗口大小的时候,就会触发resize事件(resizeEvent)

像resize这样的事件,是连续变化的.把窗口尺寸从A拖到B这个过程中,会触发出一系列的resizeEvent

在实际编程中,指定回调函数其实有很多种写法

  1. 设置函数指针
  2. 设置仿函数(函数对象)
  3. 设置 lambda
  4. 通过重写父类虚函数(框架中拿着父类的指针调用这个函数。如果你创建了子类重写了这个函数,此时在多态机制下,实际执行的就是子类的函数了)
  5. Qt 的信号槽

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setText("这是一段文本");
    //| :按位或
    ui->label->setAlignment(Qt::AlignHCenter |Qt::AlignVCenter );//水平居中对齐,垂直居中对齐

    ui->label_2->setText("这是一段文本");
    //| :按位或
    ui->label_2->setAlignment(Qt::AlignRight |Qt::AlignVCenter );//水平向右对齐,垂直居中对齐

    ui->label_3->setText("这是一段文本");
    //| :按位或
    ui->label_3->setAlignment(Qt::AlignRight |Qt::AlignTop );//水平向右对齐,垂直向上对齐



}

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


wigdet.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

实现自动换行

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    //设置自动换行
    ui->label->setText("这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本");
    ui->label->setWordWrap(true);



}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

设置缩进,设置的缩进即使文本换行了,后续的行也会产生缩进,不仅仅是首行缩进

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


      //设置缩进
    ui->label->setText("这是一段文本");//设置的缩进即使文本换行了,后续的行也会产生缩进,不仅仅是首行缩进
    ui->label->setIndent(50) ;
	   ui->label->setMargin(100) ;  //设置边距

}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

&A , 通过键盘上的alt +a 来触发这个快捷键

&B , 通过键盘上的alt +B 来触发这个快捷键

绑定伙伴关系后,通过快捷键可以选中对应的单选按钮/复选按钮

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
   //设置label和radiobutton 的伙伴关系
    
    ui->label->setBuddy(ui->radioButton) ;
     ui->label_2->setBuddy(ui->radioButton_2) ;
}

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

使用QLCDNumber 实现一个倒计时,从0开始,到100结束

通过QTimer 这个类创建对象, 就会产生一个timeout这样的信号

通过start方法来开启定时器,并且参数中设定触发timeout 信号的周期

结合connect,将timeout信号绑定到对应的槽函数中 ,即可修改LCDNumber中的数字

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->lcdNumber->display("10");
   timer =  new QTimer(this) ;

    //将timeout与槽函数handle 连接
    connect(timer, &QTimer::timeout , this , &Widget::handle);
       timer->start(1000) ;
}

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

void Widget::handle()
{
  int value = ui->lcdNumber->intValue();
  if(value <=0)
  {
      timer->stop();
      return ;
  }
   ui->lcdNumber->display(value -1);
}


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
       void  handle() ;
private:
    Ui::Widget *ui;
    QTimer * timer ;
};
#endif // WIDGET_H

请看下面的一段代码

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<thread>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    int value  = ui->lcdNumber->intValue();
    while(true)
    {
        //先休眠1s
        std::this_thread::sleep_for(std::chrono::seconds(1)) ;

        if(value <=0)
        {
            break;
        }
        value-= 1 ;
        ui->lcdNumber->display(value);

    }
}

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H


上述代码中出现了问题: 需要等待10s,才能出现结果

问题原因:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决方案:

在构造函数中,另外创建一个线程,在新的线程中,执行上述循环+更新操作

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<thread>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    
    
    //在构造函数中,另外创建一个线程,在新的线程中,执行上述循环+更新操作
    //这样写出现了问题:terminate called without an active exception
   
    std::thread t (  [this] ()
    {
         int value  = ui->lcdNumber->intValue();
            while(true)
            {
                //先休眠1s
                std::this_thread::sleep_for(std::chrono::seconds(1)) ;

                if(value <=0)
                {
                    break;
                }
                value-= 1 ;
                ui->lcdNumber->display(value);

            }
    }) ;



}

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


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

上述解决方案是不可行的

问题原因:Qt里,界面有一个专门的线程去负责维护更新的(主线程), 主线程就是main函数所在的线程

对于GUI来说,,内部包含了很多的隐藏状态,Qt为了保证修改界面的过程中,不会因为线程安全受到影响, Qt禁止了其他线程直接修改界面.

   ui->lcdNumber->display(value);//这段代码 ,属于其他线程直接修改界面

因此Qt为了确保线程安全,要求所有的对界面的修改操作,必须在主线程中完成

对于Qt的槽函数来说,默认情况下,槽函数都是由主线程调用的.在槽函数中修改界面是没有任何问题的


http://www.kler.cn/a/525927.html

相关文章:

  • 青少年编程与数学 02-008 Pyhon语言编程基础 07课题、数字
  • Linux pkill 命令使用详解
  • 2025美赛数学建模MCM/ICM选题建议与分析,思路+模型+代码
  • Base64详解
  • HTML<kbd>标签
  • 园区管理智能化创新引领企业效能提升与风险控制新趋势
  • 对于RocksDB和LSM Tree的一些理解
  • 【MySQL】数据类型与表约束
  • 设想中的计算机语言:可执行对象的构造函数和析构函数
  • Vue.js路由管理与自定义指令深度剖析
  • Python | Pytorch | Tensor知识点总结
  • 智能汽车网络安全威胁报告
  • k8s--部署k8s集群--控制平面节点
  • 春节期间,景区和酒店如何合理用工?
  • DOM操作中childNodes与children的差异及封装方案
  • 算法随笔_30: 去除重复字母
  • 显示当前绑定变量
  • 【Elasticsearch】内置分词器和IK分词器
  • 【VASP】AIMD计算总结
  • 《千朵桃花一世开》浅谈
  • WGCLOUD服务器资源监控软件使用笔记 - Token is error是什么错误
  • Paddle和pytorch不可以同时引用
  • 实战LLM强化学习——使用GRPO(DeepSeek R1出圈算法)
  • 论文阅读(八):结构方程模型用于研究数量遗传学中的因果表型网络
  • 拦截器快速入门及详解
  • 词表设计:特殊Token区域与共享去区域的深入探讨