QtStudy
Qt
容器&布局
QGridLayout
- 网格布局
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
qgride=new QGridLayout(this);
button1=new QPushButton(this);
button1->setText("区域一:顶部菜单栏");
button1->setFixedHeight(40);
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2=new QPushButton(this);
button2->setText("区域二:侧边栏");
button2->setFixedWidth(150);
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3=new QPushButton(this);
button3->setText("区域三:底部");
button3->setFixedHeight(40);
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
qgride->setContentsMargins(0,0,0,0);
qgride->setSpacing(0);
qgride->addWidget(button1,0,1);
//占据第0行第0列,跨三行一列
qgride->addWidget(button2,0,0,3,1);
qgride->addWidget(button3,3,1);
//如果需要grid在UI中生效,需要添加下面这段代码
this->centralWidget()->setLayout(qgride);
}
MainWindow::~MainWindow()
{
delete ui;
}
[!note]
在MainWindow窗体下,布局都需要在最后加上this,这样运行才能在ui上看见
QFormLayout
- 表单格式
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
form=new QFormLayout(this);
name=new QLineEdit;
name->setPlaceholderText("请输入名字");
sex=new QLineEdit;
sex->setPlaceholderText("随便");
form->addRow("姓名:",name);
form->addRow("年龄",sex);
}
Widget::~Widget() {}
[!warning]
创建的是Qwidget窗体而不是QMainWindow
垂直布局
水平布局
命令按钮组控件
push button
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//设置窗体在做面起始位置,以及窗体大小
this->setGeometry(300,150,500,400);
p1=new QPushButton("按钮1",this);
p2=new QPushButton("按钮2",this);
//设置按钮位置与大小
p1->setGeometry(20,20,150,50);
p2->setGeometry(20,90,150,50);
//与信号槽函数连接
connect(p1,SIGNAL(clicked()),this,SLOT(button_add1()));
connect(p2,SIGNAL(clicked()),this,SLOT(button_add2()));
}
MainWindow::~MainWindow() {}
void MainWindow::button_add1()
{
this->setStyleSheet("QMainWindow {background-color:rgba(255,255,0,100%);}");
}
void MainWindow::button_add2()
{
this->setStyleSheet("QMainWindow {background-color:rgb(255,26,33);}");
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QPushButton* p1,*p2;
//槽函数
private slots:
void button_add1();
void button_add2();
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
ToolButton
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//菜单栏
#include <QToolBar>
#include <QToolButton>
//样式
#include <QStyle>
#include <QApplication>
#include<QIcon>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QToolBar* tooBar;
QToolButton* toolButton;
QStyle* style;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
//设置窗体位置与大小
this->setGeometry(300,150,500,300);
tooBar=new QToolBar(this);
tooBar->setGeometry(20,20,200,50);
//设置工具栏样式风格以及图标(系统自带图标)
style=QApplication::style();
QIcon ico=style->standardIcon(QStyle::SP_TitleBarContextHelpButton);
//
toolButton=new QToolButton;
toolButton->setIcon(ico);
toolButton->setText("文件");
toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
tooBar->addWidget(toolButton);
radiobutton
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//引入单选按钮
#include<QRadioButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QRadioButton *radio,*radio2;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
this->setGeometry(300,150,500,400);
radio=new QRadioButton(this);
radio2=new QRadioButton(this);
radio->setGeometry(20,20,150,40);
radio2->setGeometry(20,80,150,40);
radio->setText("单选1");
radio2->setText("单选2");
//设置是否选中
radio->setChecked(true);
checkbutton
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCheckBox>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QCheckBox *ckbox1;
private slots:
//声明槽函数,用于对事件的连接,当相应的事件被触发时调用与其连接
//的槽函数
void checkboxstatus(int);
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setGeometry(300,150,500,400);
this->setStyleSheet("QMainWindow {background-color:rgba(255,100,0,100%);}");
ckbox1=new QCheckBox(this);
ckbox1->setGeometry(20,20,200,50);
ckbox1->setText("跑步");
//设置复选框选中状态
//ckbox1->setChecked(true) 也可以表示选中;
ckbox1->setCheckState(Qt::Checked);
//开启半选中状态
ckbox1->setTristate();
connect(ckbox1,SIGNAL(stateChanged(int)),this,SLOT(checkboxstatus(int)));
}
MainWindow::~MainWindow() = default;
void MainWindow::checkboxstatus(int status)
{
switch(status)
{
case Qt::Checked:
ckbox1->setCheckState(Qt::Checked);
break;
case Qt::Unchecked:
ckbox1->setCheckState(Qt::Unchecked);
break;
case Qt::PartiallyChecked:
ckbox1->setCheckable(Qt::PartiallyChecked);
break;
default:
break;
}
// if (status==Qt::Unchecked)
// {
// ckbox1->setCheckState(Qt::Unchecked);
// }
// else if(status==Qt::Checked)
// {
// ckbox1->setCheckState(Qt::Checked);
// }
// else
// {
// ckbox1->setCheckable(Qt::PartiallyChecked);
// }
}
commandlinkbutton
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCommandLinkButton>
//引入桌面服务
#include <QDesktopServices>
//引入url
#include <QUrl>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QCommandLinkButton* clb;
private slots:
void mycommandlik_click();
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setGeometry(300,150,500,300);
//内容信息,描述信息,widget
clb=new QCommandLinkButton("测试clb","点击测试clb",this);
clb->setGeometry(50,100,250,60);
connect(clb,SIGNAL(clicked()),this,SLOT(mycommandlik_click()));
}
MainWindow::~MainWindow() = default;
void MainWindow::mycommandlik_click()
{
QDesktopServices::openUrl(QUrl("www.baid.com"));
}
dialogbuttonbox
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QDebug>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QPushButton* btn;
QDialogButtonBox* dilogbtn;
private slots:
void open_the_dialogbtn_box(QAbstractButton*);
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setGeometry(400,300,500,400);
btn=new QPushButton("打开dialog",this);
dilogbtn=new QDialogButtonBox(this);
dilogbtn->setGeometry(100,50,200,30);
//为dialogbuttonbox添加信息和按钮类别
//dilogbtn->addButton(QDialogButtonBox::Cancel)->setText("取消");
dilogbtn->addButton(QDialogButtonBox::Cancel);
dilogbtn->button(QDialogButtonBox::Cancel)->setText("取消");
//将pushbutton添加到dialobuttonbox中,并设定按钮角色为action role
dilogbtn->addButton(btn,QDialogButtonBox::ActionRole);
connect(dilogbtn,SIGNAL(clicked(QAbstractButton*)),this,SLOT(open_the_dialogbtn_box(QAbstractButton*)));
}
MainWindow::~MainWindow() = default;
void MainWindow::open_the_dialogbtn_box(QAbstractButton* bt)
{
if(bt==dilogbtn->button(QDialogButtonBox::Cancel))
{
qDebug()<<"你已经点击【取消】按钮了";
}else if(bt==btn)
{
qDebug()<<"你已经点击【自定义】按钮了";
}
}
容器组控件
Group box 组合框
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QGroupBox>
#include <QPushButton>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QRadioButton>
#include <QGridLayout>
class Widget : public QWidget
{
Q_OBJECT
private:
QGroupBox *gb,*gb2;
QRadioButton* rbtn1,*rbtn2,*rbtn3;
QPushButton *btn;
QCheckBox *ckb,*ckb2,*ckb3;
QVBoxLayout *vbl,*vbl1;
QGridLayout* gridlayou;
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
};
#endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
gridlayou=new QGridLayout(this);
vbl=new QVBoxLayout;
vbl1=new QVBoxLayout;
gb=new QGroupBox("groub 按钮组");
rbtn1=new QRadioButton("单选按钮1");
rbtn2=new QRadioButton("单选按钮2");
rbtn3=new QRadioButton("单选按钮3");
vbl->addWidget(rbtn1);
vbl->addWidget(rbtn2);
vbl->addWidget(rbtn3);
gb->setLayout(vbl);
gb2=new QGroupBox("按钮组");
//开启是否可选按钮组中所有按钮
gb2->setCheckable(true);
ckb=new QCheckBox("全选");
ckb2=new QCheckBox("复选按钮2");
ckb3=new QCheckBox("复选按钮3");
vbl1->addWidget(ckb);
vbl1->addWidget(ckb2);
vbl1->addWidget(ckb3);
gb2->setLayout(vbl1);
gridlayou->addWidget(gb,0,0);
gridlayou->addWidget(gb2,0,1);
this->setLayout(gridlayou);
}
Widget::~Widget() = default;
SCroll Area 滚动区域
#include "widget.h"
#include <QApplication>
#include <QLabel>
#include <QScrollArea>
#include <QGridLayout>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
//设置窗口大小
w.resize(500,400);
QLabel *lb=new QLabel;
lb->setText("ddd");
//拉伸至全屏
lb->setScaledContents(true);
//获取照片
QImage imag(":/img/image/1.jpeg");
//将照片转化成pixmap并将其填充到lb中
lb->setPixmap(QPixmap::fromImage(imag));
QScrollArea *scroll=new QScrollArea;
//设置跟随窗口大小变动而变动
scroll->setWidgetResizable(true);
//总是开启横向滚动条
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//加载qlabel
scroll->setWidget(lb);
QGridLayout *grid=new QGridLayout;
grid->addWidget(scroll);
w.setLayout(grid);
w.show();
return QApplication::exec();
}
tab widget
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTabWidget>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QTabWidget* tbwidget;
QGridLayout* grid;
QLabel* lb;
QLineEdit* edit;
QPushButton* btn;
private slots:
void mesBox();
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
};
#endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
this->setGeometry(300,150,400,400);
tbwidget=new QTabWidget(this);
tbwidget->setGeometry(20,20,300,300);
tbwidget->show();
bool showtbwidget1=true;
bool showtbwidget2=false;
bool showtbwidget3=false;
bool showtbwidget4=false;
if(showtbwidget1)
{
QWidget *widg=new QWidget;
tbwidget->addTab(widg,"控制面板");
grid=new QGridLayout;
lb=new QLabel("姓名");
edit=new QLineEdit;
btn=new QPushButton("发送消息");
grid->addWidget(lb,0,0);
grid->addWidget(edit,0,1);
grid->addWidget(btn,0,2);
tbwidget->setLayout(grid);
}
if(showtbwidget2)
{
QWidget *widg2=new QWidget;
tbwidget->addTab(widg2,"控制面板2");
}
if(showtbwidget3)
{
QWidget *widg3=new QWidget;
tbwidget->addTab(widg3,"控制面板3");
}
if(showtbwidget4)
{
QWidget *widg4=new QWidget;
tbwidget->addTab(widg4,"控制面板4");
}
connect(btn,SIGNAL(clicked(bool)),this,SLOT(mesBox()));
}
Widget::~Widget() = default;
void Widget::mesBox()
{
QMessageBox::information(this,"消息","发送成功");
}
Stacked Widget 堆叠控件
Fram 框架
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->frame->setStyleSheet("background-color:yellow");
ui->frame_2->setStyleSheet("background-color:green");
ui->frame->setLineWidth(2);
ui->frame->setMidLineWidth(2);
ui->frame->setFrameShape(QFrame::Box);
ui->frame->setFrameShadow(QFrame::Plain);
ui->frame_2->setLineWidth(2);
ui->frame_2->setMidLineWidth(4);
ui->frame_2->setFrameShape(QFrame::Box);
ui->frame_2->setFrameShadow(QFrame::Sunken);
}
Widget::~Widget()
{
delete ui;
}
Widget 小部件
MdiArea MDI区域
Dock Widget 停靠窗体部件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDockWidget>
//颜色
#include <QPalette>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QDockWidget* dw;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
dw=new QDockWidget("停靠窗口",this);
//颜色设置
QPalette pt;
pt.setColor(QPalette::Window,Qt::cyan);
dw->setAutoFillBackground(true);
dw->setPalette(pt);
dw->setMaximumSize(300,300);
}
MainWindow::~MainWindow()
{
delete ui;
}
QAxWidget 封装Flash的ActiveX控件
qt项目视图
listview 清单视图
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
//清单试图
#include <QListView>
//字符串
#include <QStringListModel>
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
private:
Ui::Widget *ui;
private:
QListView* listview1;
QStringListModel* listmodel;
private slots:
void Message(const QModelIndex &list);
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(450,250);
setWindowTitle("清单列表");
listview1=new QListView(this);
listview1->setGeometry(20,20,200,150);
//创建内容
QStringList list;
list.append("运动元:篮球,足球");
list.append("游戏类:switch,怪物猎人,觅仙");
//实例话QStringListModel
listmodel=new QStringListModel;
//将list设置到QStringListModel
listmodel->setStringList(list);
//QListView设置显示的内容
listview1->setModel(listmodel);
connect(listview1,SIGNAL(clicked(QModelIndex)),this,SLOT(Message(QModelIndex)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::Message(const QModelIndex &list)
{
QMessageBox::information(NULL,"兴趣爱好","选中类型 \n"+list.data().toString());
}
treeview 树视图
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//树试图
#include <QTreeView>
#include <QStringList>
#include <QStandardItemModel>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
void initTreeViewfn();
QStandardItemModel* standmodel;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
initTreeViewfn();
}
MainWindow::~MainWindow()
{
delete ui;
}
//初始化树
void MainWindow::initTreeViewfn()
{
standmodel=new QStandardItemModel(ui->treeView);
QStringList list;
list.append("编号");
list.append("初中部");
standmodel->setHorizontalHeaderLabels(list);
//创建一级节点
QList<QStandardItem*> item;
QStandardItem *it=new QStandardItem;
QStandardItem *it2=new QStandardItem;
it->setText("1");
it2->setText("初中部");
item.append(it);
item.append(it2);
//第一个二级节点
QList<QStandardItem*> it_1;
QStandardItem *ite=new QStandardItem;
QStandardItem* ite2=new QStandardItem;
ite->setText("3");
ite2->setText("三年级");
it_1.append(ite);
it_1.append(ite2);
it->appendRow(it_1);
standmodel->appendRow(item);
//第二个一级节点
QList<QStandardItem*> item2;
QStandardItem *its=new QStandardItem;
QStandardItem *its2=new QStandardItem;
its->setText("2");
its2->setText("高中部");
item2.append(its);
item2.append(its2);
standmodel->appendRow(item2);
ui->treeView->setModel(standmodel);
}
tableview 表视图
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void initTableView();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
initTableView();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initTableView()
{
QStandardItemModel* itemodel=new QStandardItemModel;
QStandardItem* stdi=new QStandardItem;
stdi->setText("学号");
QStandardItem* stdi2=new QStandardItem;
stdi2->setText("姓名");
QStandardItem* stdi3=new QStandardItem;
stdi3->setText("性别");
itemodel->setHorizontalHeaderItem(0,stdi);
itemodel->setHorizontalHeaderItem(1,stdi2);
itemodel->setHorizontalHeaderItem(2,stdi3);
itemodel->setHorizontalHeaderItem(3,new QStandardItem(QObject::tr("分数")));
//tableview绑定数据模型
ui->tableView->setModel(itemodel);
ui->tableView->setColumnWidth(0,120);
//禁止双击单元格进行修改
ui->tableView->setEditTriggers(QTableView::NoEditTriggers);
itemodel->setItem(0,0,new QStandardItem("30256"));
itemodel->setItem(0,1,new QStandardItem("张山"));
itemodel->setItem(0,2,new QStandardItem("男"));
itemodel->setItem(0,3,new QStandardItem("120"));
itemodel->setItem(1,0,new QStandardItem("30257"));
itemodel->setItem(1,1,new QStandardItem("李斯"));
itemodel->setItem(1,2,new QStandardItem("男"));
itemodel->setItem(1,3,new QStandardItem("500"));
//排序
itemodel->sort(3,Qt::DescendingOrder);
}
columnview 列视图
undo view 撤销命令视图
项目部件
list widget 清单控件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QListWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QListWidget *listwid=new QListWidget(this);
listwid->showFullScreen();
QListWidgetItem *title=new QListWidgetItem("注意事项");
title->setTextAlignment(Qt::AlignCenter);
QStringList list;
list<<"在线编译器适用于快速测试和调试代码,但对于大型项目,建议使用本地开发环境。";
list<<"确保您的代码没有语法错误,否则编译将失败。";
listwid->addItem(title);
listwid->addItems(list);
}
Widget::~Widget()
{
delete ui;
}
treewidget 树形控件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->treeWidget->setWindowTitle("测试控件");
QTreeWidgetItem *top=new QTreeWidgetItem(ui->treeWidget);
top->setText(0,"北京大学");
top->setCheckState(0,Qt::Checked);
ui->treeWidget->addTopLevelItem(top);
//隐藏表头
ui->treeWidget->setHeaderHidden(true);
//二级节点
QTreeWidgetItem *sec=new QTreeWidgetItem(top);
sec->setText(0,"南京大学");
sec->setCheckState(0,Qt::Checked);
}
Widget::~Widget()
{
delete ui;
}
tablewidget 表控件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->tableWidget->setRowCount(2);
ui->tableWidget->setColumnCount(2);
QStringList list;
list<<"学号"<<"分数";
ui->tableWidget->setHorizontalHeaderLabels(list);
QList<QString> str;
str<<"35642"<<"461368";
QList<QString> str1;
str1<<"550"<<"600";
for(int i=0;i<2;i++)
{
int icol=0;
QTableWidgetItem *item=new QTableWidgetItem(list.at(i));
ui->tableWidget->setItem(i,icol++,item);
ui->tableWidget->setItem(i,icol++,new QTableWidgetItem(str1.at(i)));
}
}
Widget::~Widget()
{
delete ui;
}
输入控件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//COMBO BOX
#include <QComboBox>
//Fontcombobox
#include <QFontComboBox>
#include <QLabel>
//lineEdit
#include <QLineEdit>
#include <QPushButton>
//
#include <QPlainTextEdit>
//文件
#include <QDir>
#include <QRadioButton>
//文本流
#include <QTextStream>
//核心应用
#include <QCoreApplication>
//
#include <QSpinBox>
//
#include <QTimeEdit>
#include <QDateTime>
#include <QDateTimeEdit>
//
#include <QScrollBar>
//
#include <QKeySequenceEdit>
#include <QMessageBox>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui;
QComboBox *box;
private:
QFontComboBox* fontbox;
QLabel* lb;
//
QLineEdit* lines;
QPushButton* btn;
QLabel* lableshow;
//
QPlainTextEdit* plaint;
QRadioButton* rad;
//
QSpinBox* pinbox;
//
QDateTimeEdit* dte;
QDateEdit* de;
QTimeEdit* te;
//
QScrollBar* hscrbar,*vscrbar;
//
QKeySequenceEdit* keysequen;
private slots:
void showCombox(int);
void fontcomboshow(QFont);
void pushbtnclicked();
void enabledplain();
void valuechangespinbox(int);
void keysequenchange(const QKeySequence&);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//1.QComboBox
QStringList list;
list<<"德阳"<<"什邡"<<"广汉";
box=new QComboBox(this);
box->addItems(list);
connect(box,SIGNAL(currentIndexChanged(int)),this,SLOT(showCombox(int)));
//2.fontcombobox
fontbox=new QFontComboBox(this);
lb=new QLabel(this);
fontbox->setGeometry(10,50,200,30);
lb->setGeometry(10,80,300,50);
connect(fontbox,SIGNAL(currentFontChanged(QFont)),this,SLOT(fontcomboshow(QFont)));
//3.lineedit
lines=new QLineEdit(this);
btn=new QPushButton(this);
lines->setGeometry(10,90,200,30);
btn->setGeometry(220,90,100,30);
btn->setText("点击");
lableshow=new QLabel(this);
lableshow->setGeometry(10,100,200,100);
connect(btn,SIGNAL(clicked(bool)),this,SLOT(pushbtnclicked()));
//4.QPlainTextEdit
rad=new QRadioButton(this);
plaint=new QPlainTextEdit(this);
rad->setGeometry(400,110,120,80);
plaint->setGeometry(10,190,500,400);
rad->setText("开启只读模式");
//设置文件路径
QDir::setCurrent(QCoreApplication::applicationDirPath());
//打开文件名称
QFile file("moc_mainwindow.cpp");
//打开文件以只读模式读取文本信息
file.open(QFile::ReadOnly|QFile::Text);
//将文件内容读取到文本流中
QTextStream stream(&file);
//读取的文本内容添加到多行编辑文本框中
plaint->setPlainText(stream.readAll());
connect(rad,SIGNAL(clicked(bool)),this,SLOT(enabledplain()));
//5.QSpinBox
this->setStyleSheet("QMainWindow {background-color:rgba(255,255,0,100%);}");
pinbox=new QSpinBox(this);
pinbox->setGeometry(540,190,100,50);
//设置数字范围
pinbox->setRange(0,100);
//设置默认值
pinbox->setValue(100);
//设置计数值
pinbox->setSingleStep(10);
pinbox->setSuffix("%透明度");
connect(pinbox,SIGNAL(valueChanged(int)),this,SLOT(valuechangespinbox(int)));
//6.
dte=new QDateTimeEdit(QDateTime::currentDateTime(),this);
dte->setGeometry(540,250,100,20);
te=new QTimeEdit(QTime::currentTime(),this);
te->setGeometry(540,280,100,20);
de=new QDateEdit(QDate::currentDate(),this);
de->setGeometry(540,310,100,20);
//7.
hscrbar=new QScrollBar(Qt::Horizontal,this);
hscrbar->setGeometry(540,340,100,20);
vscrbar=new QScrollBar(Qt::Vertical,this);
vscrbar->setGeometry(650,250,20,100);
keysequen=new QKeySequenceEdit(this);
keysequen->setGeometry(540,370,100,20);
//connect(keysequen,SIGNAL(keySequenceChanged(const QKeySequence&)),this,SLOT(keysequenchange(const QKeySequence&)));
//新写法
connect(keysequen,&QKeySequenceEdit::keySequenceChanged,this,&MainWindow::keysequenchange);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showCombox(int index)
{
QMessageBox mybo(QMessageBox::Question,"消息",box->itemText(index),QMessageBox::Yes|QMessageBox::No);
mybo.exec();
}
void MainWindow::fontcomboshow(QFont font)
{
lb->setFont(font);
QString str="特色";
lb->setText(str);
}
void MainWindow::pushbtnclicked()
{
lableshow->setText(lines->text());
}
void MainWindow::enabledplain()
{
if(rad->isChecked())
{
plaint->setReadOnly(true);
}
else
{
plaint->setReadOnly(false);
}
}
void MainWindow::valuechangespinbox(int i)
{
double dx=(double)i;
this->setWindowOpacity(dx/100);
}
void MainWindow::keysequenchange(const QKeySequence &key)
{
if(key==QKeySequence("Ctrl+Q"))
{
this->close();
}else
{
qDebug()<<key.toString();
}
}
槽函数
-
connect(object,signal(signal1),object,slot(method1))
-
一个信号可以与另一个信号相连
- connect(object,signal(signal1),object1,signal(signal2));
-
同一个信号可以与多个槽相连
- connect(object,signal(signal1),object1,slot(slot1))
- connect(object,signal(signal1),object2,slot(slot1))
-
同一个槽可以响应多个槽
- connect(object,signal(signal1),object,slot(slot1))
- connect(object2,signal(signal1),object,slot(slot1))
[!warning]
其中object表示对象,而object和object1表示不同的对象;如果您在使用 Qt Designer 时,槽函数命名遵循了
on_控件名_信号名()的规则,Qt 会自动帮您建立连接。解决方案:遇到这种情况,可以加上Qt::UniqueConnection标志位,确保同一个信号-槽对只连接一次:如connect(btn, &QPushButton::clicked, this, &MyWidget::mySlot, Qt::UniqueConnection);
示例:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QLabel* lb,*showlb;
QLineEdit* edit;
QPushButton* btn;
QGridLayout* gridlayout;
private slots:
void calculate();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
const static double PI=3.1415;
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
gridlayout=new QGridLayout(this);
lb=new QLabel;//(this);
lb->setText("请输入半径");
showlb=new QLabel;//(this);
edit=new QLineEdit;//(this);
edit->setPlaceholderText("半径值");
btn=new QPushButton;//(this);
btn->setText("计算圆球体积");
// lb->setGeometry(10,10,80,20);
// edit->setGeometry(90,10,100,20);
// btn->setGeometry(200,10,100,20);
// showlb->setGeometry(20,30,100,20);
gridlayout->addWidget(lb,0,0);
gridlayout->addWidget(edit,0,1);
gridlayout->addWidget(btn,0,2);
gridlayout->addWidget(showlb,1,0);
connect(btn,&QPushButton::clicked,this,&Dialog::calculate);
}
Dialog::~Dialog() = default;
void Dialog::calculate()
{
int r=edit->text().toInt();
double tj=(r*r*r)*PI*(4.0/3.0);
showlb->setText(QString::number(tj));
}
Qstring
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Set up code that uses the Qt event loop here.
// Call QCoreApplication::quit() or QCoreApplication::exit() to quit the application.
// A not very useful example would be including
// #include <QTimer>
// near the top of the file and calling
// QTimer::singleShot(5000, &a, &QCoreApplication::quit);
// which quits the application after 5 seconds.
// If you do not need a running Qt event loop, remove the call
// to QCoreApplication::exec() or use the Non-Qt Plain C++ Application template.
int m=QString::compare("ABCD","abcd",Qt::CaseInsensitive);
int l=QString::compare("ABCD","abcd",Qt::CaseSensitive);
qDebug()<<"m="<<m<<","<<"l="<<l;
return QCoreApplication::exec();
}
map,hash,vector
map(有序)
-
如果存在多个相同的键时,最后一个键会将前面的覆盖
-
foreach时,key,v需要提前声明
-
插入方式有两种
QMap<int,QString> map;
map[0]="ddd";
//更新值,也可以理解成后一个覆盖前一个值
map.insert(1,"kjlkj");
map.insert(1,"555");
qDebug()<<map;
-
遍历方式
-
stl标准类型迭代
-
迭代器
-
//迭代器
QMapIterator<int,QString> itr(map);
while(itr.hasNext())
{
itr.next();
qDebug()<<itr.key()<<itr.value();
}
//stl标准类型迭代
QMap<int,QString>::iterator it=map.begin();
while(it!=map.end())
{
qDebug()<<it.key()<<":"<<it.value();
it++;
}
[!warning]
如果你仅仅是为了查找某个键对应的值,强烈建议使用
map.value(key)而不是map[key]。
因为如果在查找时误用了map[key],且该键不存在,QMap会偷偷帮你创建一个默认值(例如QString会创建一个空字符串,int会创建一个0)并塞进 map 里,这可能会导致你的 map 莫名其妙多出很多无效数据,甚至引发内存问题。
QMultiMap
- 同一个键可拥有多个值
QMultiMap<int,QString> multimap;
multimap.insertMulti(0,"dd");
multimap.insertMulti(0,"88");
multimap.insert(1,"saf");
multimap.insert(1,"erwe");
qDebug()<<multimap;
hash(无序)
- 与map相同
QHash<int,QString> hs;
hs[0]="dd";
hs.insert(1,"mlk");
hs.insert(1,"sdfsd");
qDebug()<<hs;
//通过获取keys从而便利值
QList<int> list=hs.keys();
for(int i;i<list.length();i++)
{
qDebug()<<"key:"<<list[i]<<","<<"value:"<<hs.value(list[i]);
}
//stl迭代
QHash<int,QString>::const_iterator constitr;
for(constitr=hs.constBegin();constitr!=hs.constEnd();constitr++)
{
qDebug()<<"k:"<<constitr.key()<<","<<"v:"<<constitr.value();
}
vector
- 插入操作
QVector<int> vec;
vec.insert(0,2);
vec<<3;
vec.append(4);
qDebug()<<vec;
- 遍历操作
QVector<int> vec;
vec.insert(0,2);
vec<<3;
vec.append(4);
qDebug()<<vec;
//遍历元素
for(int i;i<vec.length();i++)
{
qDebug()<<vec[i];
}
list(顺序存储结构)
#include <QCoreApplication>
#include <QList>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<QString> ls;
ls.append("1");
ls.insert(0,"dsa");
ls.insert(0,"fsasf");
//普通遍历
for(int i=0;i<ls.length();i++)
{
qDebug()<<ls.at(i);
}
qDebug()<<"===========";
//迭代遍历(可读可写)
QList<QString>::iterator listr;
for(listr=ls.begin();listr!=ls.end();listr++)
{
//解引用
qDebug()<<(*listr);
*listr=(*listr)+"10";
}
qDebug()<<"===========";
//只读
QList<QString>::const_iterator constitr;
for(constitr=ls.constBegin();constitr!=ls.constEnd();constitr++)
{
qDebug()<<(*constitr);
}
qDebug()<<"========";
//查询值
qDebug()<<ls.at(0);
qDebug()<<ls.value(1);
qDebug()<<ls.contains("110");
qDebug()<<ls.contains("0");
qDebug()<<"========";
//修改
ls.replace(2,"555");
qDebug()<<ls;
qDebug()<<"========";
//删除
ls.remove(0);
qDebug()<<ls;
return QCoreApplication::exec();
}
link list(链式存储)
-
顺序存储查询快,末尾插入快;而链式存储插/删除入快,查询慢;qt6去除了qlinkedlist
-
改用std::list
std::list<QString> ls;
ls.push_back("dasz");
ls.push_front("1");
//插入数据尾部
ls.insert(ls.end(),"dd");
//插入指定位置数据
auto index= std::next(ls.begin(),1);
ls.insert(index,"mm");
qDebug()<<ls;
//stl标准类型迭代
std::list<QString>::iterator litr;
for(litr=ls.begin();litr!=ls.end();litr++)
{
qDebug()<<*litr;
}
variant
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVariant>
#include <QDebug>
#include <QMap>
#include <QColor>
#include <QString>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QVariant qvs("ddd");
qDebug()<<qvs.toString();
QVariant qint(125);
qDebug()<<qint.toInt();
qDebug()<<"============";
QMap<QString,QVariant> map;
map["1"]="dsd";
map["2"]=123;
map["3"]=123.5;
map["4"]=QColor(255,255,100);
qDebug()<<map["1"]<<map["1"].toString();
qDebug()<<map["2"]<<map["2"].toInt();
qDebug()<<map["3"]<<map["3"].toDouble();
qDebug()<<map["4"]<<map["4"].value<QColor>();
qDebug()<<"============";
QStringList strlist;
strlist.append("a");
strlist.append("b");
strlist.append("c");
strlist.append("d");
QVariant vstr(strlist);
if(vstr.type()==QVariant::StringList)
{
for (int i = 0; i < vstr.toStringList().length(); ++i) {
qDebug()<<vstr.toStringList().at(i);
}
//qDebug()<<vstr.toStringList();
}
qDebug()<<"============";
struct student
{
QString name;
int age;
QString sex;
};
student stu;
stu.name="张三";
stu.age=8;
stu.sex="男";
QVariant qvstu=QVariant::fromValue(stu);
qDebug()<<qvstu.canConvert<student>();
if(qvstu.canConvert<student>())
{
student st= qvstu.value<student>();
student te=qvariant_cast<student>(qvstu);
qDebug()<<"name:"<<st.name<<"age:"<<te.age<<"sex:"<<st.sex;
}
}
MainWindow::~MainWindow() = default;
layout
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QTextEdit>
#include <QGridLayout>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private:
QGridLayout* grid,*algrid;
QLabel* userid;
QLabel* username;
QLabel* usersex;
QLabel* userdepart;
QLabel* userage;
QLineEdit* idedit;
QLineEdit* nameeidt;
QComboBox* sexcombox;
QTextEdit* departedit;
QLineEdit* ageedit;
QLabel* indivatual_information;
QTextEdit* infor;
QHBoxLayout* horb,*hb;
QVBoxLayout* vb;
QPushButton* surebtn,*cancelbtn;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle("消息表");
grid=new QGridLayout;
userid=new QLabel("用户编号:");
username=new QLabel("用户名");
userage=new QLabel("用户年龄");
usersex=new QLabel("用户性别");
userdepart=new QLabel("用户部门");
idedit=new QLineEdit;
nameeidt=new QLineEdit;
ageedit=new QLineEdit;
sexcombox=new QComboBox;
sexcombox->addItem("男");
sexcombox->addItem("女");
departedit=new QTextEdit;
ageedit=new QLineEdit;
grid->addWidget(userid,0,0);
grid->addWidget(idedit,0,1);
grid->addWidget(username,1,0);
grid->addWidget(nameeidt,1,1);
grid->addWidget(userage,2,0);
grid->addWidget(ageedit,2,1);
grid->addWidget(usersex,3,0);
grid->addWidget(sexcombox,3,1);
grid->addWidget(userdepart,4,0);
grid->addWidget(departedit,4,1);
//个人简历
indivatual_information=new QLabel("个人简历");
infor=new QTextEdit;
vb=new QVBoxLayout;
vb->addWidget(indivatual_information);
vb->addWidget(infor);
//按钮
surebtn=new QPushButton("ok");
cancelbtn=new QPushButton("cancel");
hb=new QHBoxLayout;
hb->addStretch();
hb->addWidget(cancelbtn);
hb->addWidget(surebtn);
//
algrid=new QGridLayout(this);
algrid->addLayout(grid,0,0);
algrid->addLayout(vb,0,1);
algrid->addLayout(hb,1,0,1,2);
}
Dialog::~Dialog() = default;
stackwidget
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QListWidget>
#include <QStackedWidget>
#include <QLabel>
#include <QHBoxLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QListWidget* list;
QStackedWidget* stack;
QLabel* lb1,*lb2,*lb3,*lb4;
QHBoxLayout* hb;
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle("堆栈窗口");
list=new QListWidget;
list->addItem("linux1");
list->addItem("linux2");
list->addItem("linux3");
list->addItem("linux4");
list->addItem("linux5");
lb1=new QLabel("linux1 qt");
stack=new QStackedWidget;
stack->addWidget(lb1);
hb=new QHBoxLayout;
hb->addWidget(list);
hb->addWidget(stack,0,Qt::AlignCenter);
hb->setStretchFactor(list,1);
hb->setStretchFactor(stack,5);
setLayout(hb);
}
Dialog::~Dialog() = default;
[!warning]
stackedwidget一次只能显示一个控件
splitter
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSplitter>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QSplitter *split,*righsplit;
QTextEdit* leftedit,*righteditup,*righteditdown;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
split=new QSplitter(Qt::Horizontal,0);
leftedit=new QTextEdit("左窗口",split);
righsplit=new QSplitter(Qt::Vertical,split);
righteditup=new QTextEdit("有上窗口",righsplit);
righteditdown=new QTextEdit("有下窗口",righsplit);
split->show();
}
MainWindow::~MainWindow() = default;
dockWidget 停靠窗口
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextEdit>
#include <QDockWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void DockWidgetFn();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
DockWidgetFn();
}
MainWindow::~MainWindow() = default;
void MainWindow::DockWidgetFn()
{
setWindowTitle("widget测试");
QTextEdit *maintext=new QTextEdit;
maintext->setAlignment(Qt::AlignCenter);
//将maintext设置为主窗体的中央窗体
setCentralWidget(maintext);
QDockWidget* dwt1=new QDockWidget("停靠窗口1",this);
dwt1->setFeatures(QDockWidget::DockWidgetMovable);
dwt1->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
QTextEdit* edit=new QTextEdit;
dwt1->setWidget(edit);
addDockWidget(Qt::RightDockWidgetArea,dwt1);
QDockWidget * dwt2=new QDockWidget("停靠窗口2",this);
QTextEdit* ed=new QTextEdit;
dwt2->setWidget(ed);
dwt2->setFeatures(QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable);
addDockWidget(Qt::RightDockWidgetArea,dwt2);
}
QDialog
QFileDialog
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
class Dialog : public QDialog
{
Q_OBJECT
private:
QPushButton *openfile,*getsize;
QLabel* filename,*lb2;
QHBoxLayout* hb,*hb2;
QVBoxLayout* vb;
QLineEdit* edit,*filesize;
private slots:
void openfilepath();
void getsizefile();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
hb=new QHBoxLayout;
hb2=new QHBoxLayout;
vb=new QVBoxLayout(this);
filename=new QLabel("文件名称");
edit=new QLineEdit;
openfile=new QPushButton("选择..");
lb2=new QLabel("文件大小");
filesize=new QLineEdit;
getsize=new QPushButton("获取文件大小");
hb->addWidget(filename);
hb->addWidget(edit);
hb->addWidget(openfile);
hb2->addWidget(lb2);
hb2->addWidget(filesize);
vb->addLayout(hb);
vb->addLayout(hb2);
vb->addWidget(getsize);
connect(openfile,&QPushButton::clicked,this,&Dialog::openfilepath,Qt::UniqueConnection);
connect(getsize,&QPushButton::clicked,this,&Dialog::getsizefile);
}
Dialog::~Dialog() = default;
void Dialog::openfilepath()
{
//打开文件
QString strfile=QFileDialog::getOpenFileName(this,"打开文件","/","Files(*)");
edit->setText(strfile);
}
void Dialog::getsizefile()
{
QString strpath=edit->text();
//获取文件信息
QFileInfo fileinfo(strpath);
qint64 filesizes=fileinfo.size();
filesize->setText(QString::number(filesizes));
}
colordialog
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QColorDialog>
#include <QFrame>
#include <QGridLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QGridLayout* grid;
QPushButton* btn;
QFrame* colorFrame;
private slots:
void displaycolor();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
grid=new QGridLayout(this);
btn=new QPushButton("打开颜色对话框");
colorFrame=new QFrame;
colorFrame->setFrameShape(QFrame::Box);
colorFrame->setAutoFillBackground(true);
grid->addWidget(btn,0,0);
grid->addWidget(colorFrame,1,0);
connect(btn,&QPushButton::clicked,this,&Dialog::displaycolor);
}
Dialog::~Dialog() = default;
void Dialog::displaycolor()
{
QColor color=QColorDialog::getColor(Qt::blue);
if(color.isValid())
{
colorFrame->setPalette(QPalette(color));
}
}
fontdialog
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QLineEdit>
#include <QFontDialog>
#include <QGridLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QPushButton* fontbtn;
QLineEdit* fontedit;
QGridLayout* grid;
private slots:
void displayfont();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
grid=new QGridLayout(this);
fontbtn=new QPushButton("打开字体对话框");
fontedit=new QLineEdit;
fontedit->setText("测试");
grid->addWidget(fontbtn,0,0);
grid->addWidget(fontedit,0,1);
connect(fontbtn,&QPushButton::clicked,this,&Dialog::displayfont);
}
Dialog::~Dialog() = default;
void Dialog::displayfont()
{
bool flag;
QFont font=QFontDialog::getFont(&flag);
if(flag)
{
fontedit->setFont(font);
}
}
inputdialog
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
//输入框
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QGridLayout>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
private:
QGridLayout* grid;
QPushButton* namebtn,*numberbtn,*sexbtn,*agebtn;
QLineEdit* nameedit,*numberedit,*sexedit,*ageedit;
private slots:
void showname();
void shownumber();
void showsex();
void showage();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
grid=new QGridLayout(this);
namebtn=new QPushButton("学生名称");
nameedit=new QLineEdit("张三");
numberbtn=new QPushButton("学生编号");
numberedit=new QLineEdit("135465");
sexbtn=new QPushButton("学生性别");
sexedit=new QLineEdit("男");
agebtn=new QPushButton("学生年龄");
ageedit=new QLineEdit("18");
grid->addWidget(namebtn,0,0);
grid->addWidget(nameedit,0,1);
grid->addWidget(numberbtn,1,0);
grid->addWidget(numberedit,1,1);
grid->addWidget(sexbtn,2,0);
grid->addWidget(sexedit,2,1);
grid->addWidget(agebtn,3,0);
grid->addWidget(ageedit,3,1);
connect(namebtn,&QPushButton::clicked,this,&Dialog::showname);
connect(numberbtn,&QPushButton::clicked,this,&Dialog::shownumber);
connect(sexbtn,&QPushButton::clicked,this,&Dialog::showsex);
connect(agebtn,&QPushButton::clicked,this,&Dialog::showage);
}
Dialog::~Dialog() = default;
void Dialog::showname()
{
bool flag;
QString str= QInputDialog::getText(this,"输入对话框","请输入姓名",QLineEdit::Normal,nameedit->text(),&flag);
if(!str.isEmpty()&&flag)
{
nameedit->setText(str);
}
}
void Dialog::shownumber()
{
bool flag;
QString nu=QInputDialog::getText(this,"输入对话框","请输入编号",QLineEdit::Normal,numberedit->text(),&flag);
if(flag&&!nu.isEmpty())
{
numberedit->setText(nu);
}
}
void Dialog::showsex()
{
QStringList sexlist;
sexlist<<"男"<<"女";
bool flag;
QString nu=QInputDialog::getItem(this,"输入对话框","请输入性别", sexlist,0,false,&flag);
if(flag&&!nu.isEmpty())
{
sexedit->setText(nu);
}
}
void Dialog::showage()
{
bool flag;
QString nu=QInputDialog::getText(this,"输入对话框","请输入年龄",QLineEdit::Normal,ageedit->text(),&flag);
if(flag&&!nu.isEmpty())
{
ageedit->setText(nu);
}
}
messagebox
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QGridLayout>
#include <QMessageBox>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
private:
QLabel* mess;
QGridLayout* grid;
QPushButton* questbtn,*inforbtn,*warningbtn,*criticlbtn,*aboutbtn,*aboutqtbtn;
private slots:
void showquest();
void showinfor();
void showwarning();
void showcriticl();
void showabout();
void showaboutqt();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
resize(300,200);
grid=new QGridLayout(this);
mess=new QLabel("请选择一个消息框");
questbtn=new QPushButton("问题消息框");
inforbtn=new QPushButton("信息消息框");
warningbtn=new QPushButton("警告消息框");
criticlbtn=new QPushButton("错误消息框");
aboutbtn=new QPushButton("关于消息框");
aboutqtbtn=new QPushButton("关于qt消息框");
grid->addWidget(mess,0,0);
grid->addWidget(questbtn,1,0);
grid->addWidget(inforbtn,2,0);
grid->addWidget(warningbtn,3,0);
grid->addWidget(criticlbtn,4,0);
grid->addWidget(aboutbtn,5,0);
grid->addWidget(aboutqtbtn,6,0);
connect(questbtn,&QPushButton::clicked,this,&Dialog::showquest);
connect(inforbtn,&QPushButton::clicked,this,&Dialog::showinfor);
connect(warningbtn,&QPushButton::clicked,this,&Dialog::showwarning);
connect(criticlbtn,&QPushButton::clicked,this,&Dialog::showcriticl);
connect(aboutbtn,&QPushButton::clicked,this,&Dialog::showabout);
connect(aboutqtbtn,&QPushButton::clicked,this,&Dialog::showaboutqt);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::showquest()
{
mess->setText("问题消息框");
switch(QMessageBox::question(this,"问题消息","是否退出应用程序?",QMessageBox::Ok|QMessageBox::Cancel))
{
case QMessageBox::Ok:
mess->setText("你选择了问题消息框");
break;
case QMessageBox::Cancel:
mess->setText("你选择退出问题消息框");
break;
default:
break;
}
}
void Dialog::showinfor()
{
mess->setText("信息消息框");
switch(QMessageBox::information(this,"信息消息","是否退出应用程序?",QMessageBox::Ok|QMessageBox::Cancel))
{
case QMessageBox::Ok:
mess->setText("你选择了信息消息框");
break;
case QMessageBox::Cancel:
mess->setText("你选择退出信息消息框");
break;
default:
break;
}
}
void Dialog::showwarning()
{
mess->setText("警告消息框");
switch(QMessageBox::warning(this,"警告消息","是否退出应用程序?",QMessageBox::Ok|QMessageBox::Cancel))
{
case QMessageBox::Ok:
mess->setText("你选择了警告消息框");
break;
case QMessageBox::Cancel:
mess->setText("你选择退出问题警告框");
break;
default:
break;
}
}
void Dialog::showcriticl()
{
mess->setText("错误消息框");
switch(QMessageBox::critical(this,"错误消息","是否退出应用程序?",QMessageBox::Ok|QMessageBox::Cancel))
{
case QMessageBox::Ok:
mess->setText("你选择了错误消息框");
break;
case QMessageBox::Cancel:
mess->setText("你选择退出错误消息框");
break;
default:
break;
}
}
void Dialog::showabout()
{
mess->setText("关于消息框");
QMessageBox::about(this,"关于消息","是否退出应用程序?");
}
void Dialog::showaboutqt()
{
mess->setText("关于qt消息框");
QMessageBox::aboutQt(this,"关于qt消息");
}
自定义消息框
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>
#include <QMessageBox>
class Dialog : public QDialog
{
Q_OBJECT
private:
QLabel*lb,*disp;
QPushButton*btn;
QGridLayout*grid;
private slots:
void custommes();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
grid=new QGridLayout(this);
lb=new QLabel("自定义消息框");
btn=new QPushButton("测试操作");
disp=new QLabel("未测试状态");
grid->addWidget(lb,0,0);
grid->addWidget(btn,0,1);
grid->addWidget(disp,1,0,1,1);
connect(btn,&QPushButton::clicked,this,&Dialog::custommes);
}
Dialog::~Dialog() = default;
void Dialog::custommes()
{
QMessageBox mymesbo;
mymesbo.setWindowTitle("自定义");
QPushButton* mybtn=mymesbo.addButton("YES",QMessageBox::ActionRole);
QPushButton* no=mymesbo.addButton("NO",QMessageBox::ActionRole);
mymesbo.setIconPixmap(QPixmap("/home/study/Pictures/图片/3.jpeg"));
mymesbo.exec();
if(mymesbo.clickedButton()==mybtn)
{
disp->setText("点击yes");
}else if(mymesbo.clickedButton()==no)
{
disp->setText("点击no");
}
}
绘图原理双缓存机制
常用窗口api函数
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QGridLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QGridLayout* grid;
QLabel*geometrylb,*geometry_value;
QLabel*geometry_width,*geometry_val_width,*geometry_height,*geometry_val_height;
QLabel*geometry_rect,*geometry_val_rect,*geometry_size,*geometry_val_size;
private slots:
void resizeEvent(QResizeEvent*);
void moveEvent(QMoveEvent*);
public:
void updatedata();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(300,160);
grid=new QGridLayout(this);
geometrylb=new QLabel("Geometry():");
geometry_value=new QLabel;
geometry_width=new QLabel("宽度:");
geometry_val_width=new QLabel;
geometry_height=new QLabel("高度");
geometry_val_height=new QLabel;
geometry_rect=new QLabel("rect():");
geometry_val_rect=new QLabel;
geometry_size=new QLabel("size:");
geometry_val_size=new QLabel;
grid->addWidget(geometrylb,0,0);
grid->addWidget(geometry_value,0,1);
grid->addWidget(geometry_width,1,0);
grid->addWidget(geometry_val_width,1,1);
grid->addWidget(geometry_height,2,0);
grid->addWidget(geometry_val_height,2,1);
grid->addWidget(geometry_rect,3,0);
grid->addWidget(geometry_val_rect,3,1);
grid->addWidget(geometry_size,4,0);
grid->addWidget(geometry_val_size,4,1);
updatedata();
}
Dialog::~Dialog() = default;
void Dialog::resizeEvent(QResizeEvent *)
{
updatedata();
}
void Dialog::moveEvent(QMoveEvent *)
{
updatedata();
}
void Dialog::updatedata()
{
QString Geometry,str1,str2,str3,str4;
Geometry=str1.setNum(geometry().x())+","+str2.setNum(geometry().y())+","+
str3.setNum(geometry().width())+","+str4.setNum(geometry().height());
geometry_value->setText(Geometry);
QString rects,strrect1,strrect2,strrect3,strrect4;
rects=strrect1.setNum(rect().x())+","+strrect2.setNum(rect().y())+","+
strrect3.setNum(rect().width())+","+strrect4.setNum(rect().height());
geometry_val_width->setText(QString::number(geometry().width()));
geometry_val_height->setText(QString::number(geometry().height()));
geometry_val_rect->setText(rects);
geometry_val_size->setText(QString::number(size().width())+","+QString::number(size().height()));
}
Painter
#ifndef PAINTERAREA_H
#define PAINTERAREA_H
#include <QWidget>
#include <QPainter>
//画笔(基本的图形对象,如直线,矩形,多边形等)
#include <QPen>
//画刷(基本的图形对象,如直线,矩形,多边形等)主要用于填充对象
#include <QBrush>
class PainterArea : public QWidget
{
Q_OBJECT
public:
explicit PainterArea(QWidget *parent = nullptr);
enum shape
{
Line,rectangle,circle
};
void setShap(shape);
void setPen(QPen);
void setBrush(QBrush);
void paintEvent(QPaintEvent*);
void setfillrule(Qt::FillRule);
private:
shape sh;
QPen pen;
QBrush brs;
Qt::FillRule fillrule;
signals:
};
#endif // PAINTERAREA_H
#include "painterarea.h"
PainterArea::PainterArea(QWidget *parent)
: QWidget{parent}
{
setPalette(QPalette(Qt::white));
setAutoFillBackground(true);
setMinimumSize(410,410);
}
void PainterArea::setShap(shape s)
{
sh=s;
update();
}
void PainterArea::setPen(QPen p)
{
pen=p;
update();
}
void PainterArea::setBrush(QBrush b)
{
brs=b;
update();
}
void PainterArea::paintEvent(QPaintEvent *)
{
QPainter p(this);
//pen.setBrush(brs);
p.setPen(pen);
p.setBrush(brs);
QRect rec(55,110,290,180);
switch (sh) {
case Line:
p.drawLine(rec.topLeft(),rec.bottomRight());
break;
case rectangle:
p.drawRect(rec);
break;
case circle:
p.drawEllipse(rec);
default:
break;
}
}
void PainterArea::setfillrule(Qt::FillRule f)
{
fillrule=f;
update();
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QGridLayout>
#include <QComboBox>
#include "painterarea.h"
#include <QColorDialog>
#include <QDebug>
#include <QHBoxLayout>
class Widget : public QWidget
{
Q_OBJECT
private:
PainterArea *paintare;
QLabel *shlb;
QComboBox* shapecommbox;
QGridLayout* grid;
QHBoxLayout* hb;
private slots:
void displayShape(int);
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
};
#endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
grid=new QGridLayout;
paintare=new PainterArea;
shlb=new QLabel("形状");
shapecommbox=new QComboBox;
shapecommbox->addItem("Line",PainterArea::Line);
shapecommbox->addItem("Rectangle",PainterArea::rectangle);
shapecommbox->addItem("Circle",PainterArea::circle);
grid->addWidget(shapecommbox,0,1);
grid->addWidget(shlb,0,0);
hb=new QHBoxLayout(this);
hb->addWidget(paintare);
hb->addLayout(grid);
connect(shapecommbox,&QComboBox::currentIndexChanged,this,&Widget::displayShape);
}
Widget::~Widget() = default;
void Widget::displayShape(int indx)
{
PainterArea::shape sh=PainterArea::shape(shapecommbox->itemData(indx).toInt());
paintare->setShap(sh);
QColor color=QColorDialog::getColor(Qt::blue);
QBrush brsh(color);
// paintare->setBrush(static_cast<QBrush>(color));
paintare->setBrush(brsh);
}
双缓存机制
#ifndef DRAWWIDGETS_H
#define DRAWWIDGETS_H
#include <QWidget>
#include <QtGui>
//鼠标事件
#include <QMouseEvent>
//绘画事件
#include <QPaintEvent>
//窗体大小改变重绘设置
#include <QResizeEvent>
//显示图像
#include <QPixmap>
#include <QColor>
//画笔
#include <QPainter>
#include <QPen>
//颜色相关
#include <QPalette>
#include <QDebug>
class DrawWidgetS : public QWidget
{
Q_OBJECT
public:
explicit DrawWidgetS(QWidget *parent = nullptr);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
//绘制事件
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
signals:
private:
//用于显示图像而设计和优化的
QPixmap* pix;
QPoint startPoint,endPoint;
int style,widths;
QColor color;
public slots:
void setStyle(int);
void setWidth(int);
void setColor(QColor);
void clearAll();
};
#endif // DRAWWIDGETS_H
#include "drawwidgets.h"
DrawWidgetS::DrawWidgetS(QWidget *parent)
: QWidget{parent}
{
setPalette(QPalette(Qt::white));
setAutoFillBackground(true);
pix=new QPixmap(size());
pix->fill(Qt::white);
//设置绘制区域大小
setMinimumSize(600,400);
}
void DrawWidgetS::mousePressEvent(QMouseEvent *event)
{
//开始位置为鼠标当前位置
// 【关键修复】必须判断是鼠标左键才记录起点
if (event->button() == Qt::LeftButton) {
startPoint = event->pos();
}
}
void DrawWidgetS::mouseMoveEvent(QMouseEvent *event)
{
// 【关键修复】必须检查左键是否处于按下状态
// Linux 下如果不加这个,鼠标划过都会触发逻辑,导致 startPoint 被错误更新
if (!(event->buttons() & Qt::LeftButton)) {
return;
}
//初始化绘画
QPainter painter(pix);
//初始化画笔
QPen pen;
Qt::PenStyle currentStyle = static_cast<Qt::PenStyle>(style);
qDebug()<<currentStyle;
if (currentStyle == Qt::NoPen && widths > 0) {
// 如果设置了宽度但样式是 NoPen,强制改为 SolidLine
// 或者根据你的业务逻辑处理,这里假设 0 是误操作
currentStyle = Qt::SolidLine;
}
//设置画笔样式
pen.setStyle(currentStyle);
//设置画笔宽度
pen.setWidth(widths);
//设置画笔颜色
pen.setColor(color);
//设置绘画以图片开始或者说是填充开始绘画设备
// painter->begin(pix);
// 4. 优化线条连接处,避免快速移动时出现断点或锯齿
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
//设置绘画的画笔
painter.setPen(pen);
//画横线,从鼠标点击处开始,一直到鼠标移动到的位置
painter.drawLine(startPoint,event->pos());
//绘画结束
painter.end();
//鼠标位置更新为当前鼠标结束位置
startPoint=event->pos();
//重新渲染
update();
}
void DrawWidgetS::paintEvent(QPaintEvent *event)
{
//绘画事件,绘画位置为当前类
QPainter painter(this);
if (pix && !pix->isNull()) {
painter.drawPixmap(0, 0, *pix);
} else {
// 如果 pix 丢失,填充背景防止花屏
painter.fillRect(rect(), Qt::white);
}
// //以pixmap坐标为0,0开始绘画
// painter.drawPixmap(QPoint(0,0),*pix);
}
void DrawWidgetS::resizeEvent(QResizeEvent *event)
{
if(height()>pix->height()||width()>pix->width())
{
QPixmap *newPix=new QPixmap(size());
newPix->fill(Qt::white);
QPainter ps(newPix);
ps.drawPixmap(QPoint(0,0),*pix);
pix=newPix;
}
QWidget::resizeEvent(event);
}
void DrawWidgetS::setStyle(int st)
{
style=st;
}
void DrawWidgetS::setWidth(int wid)
{
widths=wid;
}
void DrawWidgetS::setColor(QColor colr)
{
color=colr;
}
void DrawWidgetS::clearAll()
{
QPixmap *pi=new QPixmap(size());
pi->fill(Qt::white);
pix=pi;
update();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "drawwidgets.h"
#include <QToolBar>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QToolButton>
#include <QGridLayout>
#include <QColorDialog>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
DrawWidgetS* draww;
QGridLayout* grid;
QColorDialog* colodialog;
QLabel* lbstyle,*lbwidth,lbcolor;
QToolButton* colorbtn;
QToolButton* clearbtn;
QComboBox* comb;
QSpinBox* spin;
private slots:
void displaystyle();
void displaycolor();
public:
void CreatTooBar();
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
draww=new DrawWidgetS;
draww->setColor(Qt::blue);
setMinimumSize(600,400);
setCentralWidget(draww);
CreatTooBar();
}
MainWindow::~MainWindow() = default;
void MainWindow::displaystyle()
{
draww->setStyle(comb->itemData(comb->currentIndex(),Qt::UserRole).toInt());
}
void MainWindow::displaycolor()
{
QColor color= QColorDialog::getColor(Qt::black,this);
if(color.isValid())
{
draww->setColor(color);
QPixmap pix(20,20);
pix.fill(color);
colorbtn->setPalette(QPalette(color));
}
}
void MainWindow::CreatTooBar()
{
QToolBar *toolb=addToolBar("Tool");
lbstyle=new QLabel("线形风格");
comb=new QComboBox;
comb->addItem("SolidLIne",static_cast<int>(Qt::SolidLine));
comb->addItem("DotLine",static_cast<int>(Qt::DotLine));
connect(comb,&QComboBox::activated,this,&MainWindow::displaystyle);
lbwidth=new QLabel("线宽");
spin=new QSpinBox;
spin->setValue(5);
spin->setSingleStep(1);
spin->setRange(1,100);
draww->setWidth(spin->value());
connect(spin,&QSpinBox::valueChanged,draww,&DrawWidgetS::setWidth);
colorbtn=new QToolButton;
colorbtn->setAutoFillBackground(true);
colorbtn->setPalette(QPalette(Qt::blue));
QPixmap pixmap(20,20);
pixmap.fill(Qt::black);
connect(colorbtn,&QToolButton::clicked,this,&MainWindow::displaycolor);
clearbtn=new QToolButton;
clearbtn->setText("清除配置");
connect(clearbtn,&QToolButton::clicked,draww,&DrawWidgetS::clearAll);
toolb->addWidget(lbstyle);
toolb->addWidget(comb);
toolb->addWidget(lbwidth);
toolb->addWidget(spin);
toolb->addWidget(colorbtn);
toolb->addWidget(clearbtn);
}
graphicsview
#ifndef MYGRAPHICSITEM_H
#define MYGRAPHICSITEM_H
#include <QGraphicsItem>
//用于显示图像
#include <QPixmap>
//引入颜色
#include <QPainter>
class MyGraphicsItem : public QGraphicsItem
{
public:
MyGraphicsItem(QPixmap *pixm);
private:
QPixmap pix;
public:
//只刷新固定区域,用于返回调整实际物体所在位置包含区域
QRectF boundingRect() const;
//绘图操作
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
#endif // MYGRAPHICSITEM_H
#include "mygraphicsitem.h"
MyGraphicsItem::MyGraphicsItem(QPixmap *pixm):pix(*pixm)
{
}
/**
* @brief MyGraphicsItem::boundingRect
* @return
*/
QRectF MyGraphicsItem::boundingRect() const
{
return QRectF(-2-pix.width()/2,-2-pix.height()/2,pix.width()+4,pix.height()+4);
}
/**
* @brief MyGraphicsItem::paint
* @param painter
* @param option
* @param widget
*/
void MyGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(-pix.width()/2,-pix.height()/2,pix);
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QFrame>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QSlider>
#include "mygraphicsitem.h"
#include <math.h>
#include <QDebug>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
public:
void creatControl();
private:
int angle;
qreal scalevalue;
MyGraphicsItem* mygraphicsitem;
//倾斜
qreal leanvalue;
QGraphicsView* view;
QFrame* fram;
QPixmap* pixmap;
QSlider *angles,*scaling,*leans;
private slots:
void rotalangle(int);
void scaleproportion(qreal);
void leanfn(qreal);
};
#endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setWindowTitle("图形视图框架");
angle=0;
scalevalue=2;
leanvalue=2;
QGraphicsScene *scene=new QGraphicsScene;
scene->setSceneRect(-200,-200,380,380);
QPixmap *pixm=new QPixmap("/home/study/Pictures/图片/4.webp");
//将图片添加到图源中
mygraphicsitem=new MyGraphicsItem(pixm);
//将图源添加到场景中
scene->addItem(mygraphicsitem);
//设置坐标
mygraphicsitem->setPos(0,0);
//创建视图
view=new QGraphicsView;
//将场景添加到视图中
view->setScene(scene);
//设置视图大小
view->setMinimumSize(800,600);
fram=new QFrame;
creatControl();
QHBoxLayout *hb=new QHBoxLayout;
hb->addWidget(view);
hb->addWidget(fram);
setLayout(hb);
}
Widget::~Widget() = default;
void Widget::creatControl()
{
angles=new QSlider;
angles->setOrientation(Qt::Horizontal);
angles->setRange(0,360);
QHBoxLayout *rotatel=new QHBoxLayout;
rotatel->addWidget(angles);
QGroupBox *rotateg=new QGroupBox("图形旋转");
rotateg->setLayout(rotatel);
connect(angles,&QSlider::valueChanged,this,&Widget::rotalangle);
//
scaling=new QSlider;
scaling->setOrientation(Qt::Horizontal);
scaling->setRange(0,2*scalevalue);
scaling->setValue(scalevalue);
QHBoxLayout *scalel=new QHBoxLayout;
scalel->addWidget(scaling);
QGroupBox *scaleg=new QGroupBox("图形缩放");
scaleg->setLayout(scalel);
connect(scaling,&QSlider::valueChanged,this,&Widget::scaleproportion);
//
leans=new QSlider;
leans->setOrientation(Qt::Horizontal);
leans->setRange(0,2*leanvalue);
leans->setValue(leanvalue);
QHBoxLayout *leansl=new QHBoxLayout;
leansl->addWidget(leans);
QGroupBox *leansg=new QGroupBox("图形倾斜");
leansg->setLayout(leansl);
connect(leans,&QSlider::valueChanged,this,&Widget::leanfn);
QVBoxLayout *vb=new QVBoxLayout;
vb->addWidget(rotateg);
vb->addWidget(scaleg);
vb->addWidget(leansg);
fram->setLayout(vb);
}
void Widget::rotalangle(int val)
{
view->rotate(val-angle);
angle=val;
}
void Widget::scaleproportion(qreal val)
{
qreal qs;
if(val>scalevalue)
{
qs=pow(1.1,(val-scalevalue));
}
else
{
qs=pow(1/1.1,(scalevalue-val));
}
view->scale(qs,qs);
scalevalue=val;
}
void Widget::leanfn(qreal val)
{
view->shear((val-leanvalue)/2,0);
leanvalue=val;
}
Model_View_Delegate
Model
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QSplitter>
#include <QFileSystemModel>
#include <QTreeView>
#include <QListView>
#include <QTableView>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// MainWindow w;
// w.show();
QFileSystemModel model;
model.setRootPath(QDir::currentPath());
QTreeView treeview;
QListView listview;
QTableView tableview;
//设置模型数据
treeview.setModel(&model);
listview.setModel(&model);
tableview.setModel(&model);
treeview.setSelectionMode(QAbstractItemView::MultiSelection);
listview.setSelectionModel(treeview.selectionModel());
tableview.setSelectionModel(treeview.selectionModel());
QObject::connect(&treeview,&QTreeView::doubleClicked,&listview,&QListView::setRootIndex);
QObject::connect(&treeview,&QTreeView::doubleClicked,&tableview,&QTableView::setRootIndex);
QSplitter * sp=new QSplitter;
sp->addWidget(&treeview);
sp->addWidget(&listview);
sp->addWidget(&tableview);
sp->show();
return QApplication::exec();
}
#ifndef MODEEXPEND_TABLE_H
#define MODEEXPEND_TABLE_H
#include <QAbstractTableModel>
#include <QVector>
#include <QStringList>
#include <QMap>
class modeexpend_table : public QAbstractTableModel
{
Q_OBJECT
public:
explicit modeexpend_table(QObject *parent = nullptr);
private:
QVector<short> empindex;
QVector<short> empnameindex;
QVector<short> emppartindex;
QStringList list;
QMap<short,QString> empid;
QMap<short,QString> empname;
QMap<short,QString> emppart;
private slots:
void Modelfn();
// QAbstractItemModel interface
public:
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
};
#endif // MODEEXPEND_TABLE_H
#include "modeexpend_table.h"
modeexpend_table::modeexpend_table(QObject *parent)
: QAbstractTableModel{parent}
{
empid[1]="202201";
empid[2]="202202";
empid[3]="202203";
empid[4]="202204";
empid[5]="202205";
empname[1]="张三";
empname[2]="李四";
empname[3]="王五";
empname[4]="赵六";
empname[5]="孙犁";
emppart[1]="研发部";
emppart[2]="财务部";
emppart[3]="后情部";
emppart[4]="销售部";
emppart[5]="管理部";
Modelfn();
}
void modeexpend_table::Modelfn()
{
list<<"员工编号"<<"员工姓名"<<"部门";
empindex<<1<<2<<3<<4<<5;
empnameindex<<1<<2<<3<<4<<5;
emppartindex<<1<<2<<3<<4<<5;
}
int modeexpend_table::rowCount(const QModelIndex &parent) const
{
return empindex.size();
}
int modeexpend_table::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant modeexpend_table::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
{
return QVariant();
}
if(role==Qt::DisplayRole)
{
switch(index.column())
{
case 0:
return empid[empindex[index.row()]];
break;
case 1:
return empname[empnameindex[index.row()]];
break;
case 2:
return emppart[emppartindex[index.row()]];
break;
default:
return QVariant();
}
}
return QVariant();
}
QVariant modeexpend_table::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)
{
return list[section];
}
return QAbstractTableModel::headerData(section,orientation,role);
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "modeexpend_table.h"
#include <QTableView>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MainWindow w;
//w.show();
modeexpend_table expendtable;
QTableView view;
view.setModel(&expendtable);
view.setWindowTitle("model类型扩展测试");
view.resize(500,300);
view.show();
return QApplication::exec();
}
文件操作
读写文本文件(QFile)
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//打开相应文件
QFile file("/home/study/test.txt");
//设置文件打开后的方式是只读还是能写以及是文本还是其他类型
bool flag=file.open(QIODevice::Text|QIODevice::WriteOnly);
if(!flag)
{
qDebug()<<"打开文件失败!";
}
else {
qDebug()<<"打开文件成功!";
file.write("测试文本");
file.close();
}
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
{
qDebug()<<"打开文件失败!";
}
else{
//设置缓存
char* byte=new char[1024];
//将文件内容读取到缓冲区域中,并返回剩余的字节数
qint64 count=file.readLine(byte,1024);
while((count!=0)&&(count!=-1))
{
qDebug()<<byte;
count=file.readLine(byte,1024);
}
file.close();
}
return QCoreApplication::exec();
}
读写二进制
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//一维数组
qint32 qnumb[3]={1,2,3};
//创建字节数组
QByteArray byte;
//设置字节数组大小,大小由要写入的内容决定
byte.resize(sizeof(qnumb));
for(int i=0;i<3;i++)
{
memcpy(byte.data()+i*sizeof(qint32),&qnumb[i],sizeof(qint32));
}
//打开test文件
QFile file("/home/study/test.dat");
//设置设备模式
bool flag=file.open(QIODevice::WriteOnly);
if(!flag)
{
qDebug()<<"打开文件失败!";
}
else {
qDebug()<<"打开文件成功!";
file.write(byte);
file.close();
}
//读取数据
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"打开势必";
}else
{
QByteArray readbyte;
readbyte=file.readAll();
qDebug()<<"byte:"<<readbyte;
//将二进制数据转换成char字符类型
const char* cha=readbyte.constData();
while(*cha)
{
//将char转换成qint32指针并解引用将值输出
qDebug()<<*(qint32*)cha;
cha=cha+sizeof(qint32);
}
file.close();
}
return QCoreApplication::exec();
}
读写二进文本文件
- QTextSteam:用于读取文本文件
- QDataSteam:用于读取二进字文件
TextStream
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QTextStream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("/home/study/test.txt");
if(!file.open(QIODevice::WriteOnly))
{
qDebug()<<"打开文件是失败";
}
else
{
qDebug()<<"打开文件成功";
//将文本以文本文件流形式打开
QTextStream stream(&file);
stream<<"QTextStream学习";
file.close();
}
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"打开文件是失败";
}
else
{
qDebug()<<"打开文件成功";
//将文本以文本文件流形式打开
QTextStream stream(&file);
while(!stream.atEnd())
{
qDebug()<<stream.readLine();
}
file.close();
}
return QCoreApplication::exec();
}
DataStream
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QDataStream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qint64 numb64[3]={1,2,3};
QFile file("/home/study/binary.dat");
if(!file.open(QIODevice::WriteOnly))
{
qDebug()<<"打开二进制文件失败";
}
else
{
qDebug()<<"打开二进制文件成功,正在写入数据。。。";
QByteArray byte;
byte.resize(sizeof(numb64));
for(int i=0;i<3;i++)
{
memcpy(byte.data()+i*sizeof(qint64),&numb64[i],sizeof(qint64));
}
file.write(byte);
file.close();
}
//读取二进制文件
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"打开二进制文件失败";
}
else
{
qDebug()<<"打开二进制文件成功,正在读取数据。。。";
//将二进制文件内容读取到数据流中
QDataStream dstream(&file);
qint64 readArray[3];
dstream.readRawData(reinterpret_cast<char*>(readArray),sizeof(readArray));
for(int i=0;i<3;i++)
{
qDebug()<<readArray[i];
}
file.close();
}
return QCoreApplication::exec();
}
Dir
#include <QCoreApplication>
#include <QDir>
#include <QStringList>
#include <QtDebug>
qint64 GetDirFileInfo(const QString &path);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString path;
path=QDir::currentPath();
qDebug()<<"当前目录"<<path;
GetDirFileInfo(path);
return QCoreApplication::exec();
}
qint64 GetDirFileInfo(const QString &path)
{
QDir dir(path);
qint64 size=0;
foreach (QFileInfo info, dir.entryInfoList(QDir::Files)) {
size=size+info.size();
}
foreach (QString di, dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
size=size+GetDirFileInfo(path+QDir::separator()+di);
}
char uint='B';
qint64 currentdirsize=size;
if(currentdirsize>1024)
{
currentdirsize=currentdirsize/1024;
uint='K';
if(currentdirsize>1024)
{
currentdirsize=currentdirsize/1024;
uint='M';
if(currentdirsize>1024)
{
currentdirsize=currentdirsize/1024;
uint='G';
if(currentdirsize>1024)
{
currentdirsize=currentdirsize/1024;
uint='T';
}
}
}
}
qDebug()<<"目录空间大小:"<<currentdirsize<<uint<<"\t"<<qPrintable(path);
return size;
}
综合实践
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QListWidget>
#include <QLineEdit>
#include <QDir>
#include <QListWidgetItem>
#include <QVBoxLayout>
//用于获取文件信息
#include <QFileInfoList>
class Dialog : public QDialog
{
Q_OBJECT
private:
QLineEdit *edit;
QVBoxLayout* vb;
QListWidget* listw;
public:
void showFileInforList(QFileInfoList list);
public slots:
void showDir(QDir dir);
void showDirall(QListWidgetItem* listwi);
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(500,500);
setWindowTitle("文件dir控件综合应用");
edit=new QLineEdit("/");
listw=new QListWidget;
vb=new QVBoxLayout(this);
vb->addWidget(edit);
vb->addWidget(listw);
//connect(edit,SIGNAL(returnPressed()),this,SLOT(showDir(QDir)));
connect(edit,&QLineEdit::returnPressed,this,[this](){QDir dir;showDir(dir);});
connect(listw,&QListWidget::itemDoubleClicked,this,&Dialog::showDirall);
QString path="/";
QDir rootPath(path);
QStringList strlist;
strlist<<"*";
//过滤所有文件
QFileInfoList info=rootPath.entryInfoList(strlist);
showFileInforList(info);
}
Dialog::~Dialog() = default;
void Dialog::showFileInforList(QFileInfoList list)
{
listw->clear();
for(unsigned int i=0;i<list.count();i++)
{
QFileInfo tempfile=list.at(i);
//判断是否是文件夹
if(tempfile.isDir())
{
QIcon icon("/home/study/Pictures/图片/dir.png");
QString filename=tempfile.fileName();
QListWidgetItem *temp=new QListWidgetItem(icon,filename);
listw->addItem(temp);
}
else if(tempfile.isFile())
{
QIcon icon("/home/study/Pictures/图片/text.png");
QString name=tempfile.fileName();
QListWidgetItem *tm=new QListWidgetItem(icon,name);
listw->addItem(tm);
}
}
}
void Dialog::showDir(QDir dir)
{
QStringList pathlist;
pathlist<<"*";
QFileInfoList info=dir.entryInfoList(pathlist,QDir::AllEntries,QDir::DirsFirst);
showFileInforList(info);
}
void Dialog::showDirall(QListWidgetItem *listwi)
{
QDir dir;
QString str=listwi->text();
dir.setPath(edit->text());
dir.cd(str);
edit->setText(dir.absolutePath());
showDir(dir);
}
fileinfo 获取文件信息
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QFileDialog>
#include <QDateTime>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
class Dialog : public QDialog
{
Q_OBJECT
private:
QLabel* filepath,*filesize,*filecreatetime,*filemodifytime,*fileusetime,*filemanage;
QLineEdit* pathedit,*sizeedit,*timeedit,*modifyedit,*useedit,*manageeddit;
QPushButton *openfilebtn,*getfileallproperty;
QCheckBox* file,*hiddenproperty,*readonlypower,*writeonlypower,*exepower;
QGridLayout* grid;
QVBoxLayout* vb;
QHBoxLayout* hb;
private slots:
void openfile();
void getallproperty();
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
filepath=new QLabel("文件路径:");
pathedit=new QLineEdit;
openfilebtn=new QPushButton("打开文件夹");
filesize=new QLabel("文件大小");
filecreatetime=new QLabel("文件创建时间");
filemodifytime=new QLabel("文件修改时间");
fileusetime=new QLabel("最后使用时间");
filemanage=new QLabel("文件管理");
sizeedit=new QLineEdit;
timeedit=new QLineEdit;
modifyedit=new QLineEdit;
useedit=new QLineEdit;
//manageeddit=new QLineEdit;
getfileallproperty=new QPushButton("获取文件所有信息和属性");
file=new QCheckBox("文件");
hiddenproperty=new QCheckBox("隐藏属性");
readonlypower=new QCheckBox("只读权限");
writeonlypower=new QCheckBox("只写权限");
exepower=new QCheckBox("执行权限");
hb=new QHBoxLayout;
grid=new QGridLayout;
grid->addWidget(filepath,0,0);
grid->addWidget(pathedit,0,1);
grid->addWidget(openfilebtn,0,2);
grid->addWidget(filesize,1,0);
grid->addWidget(sizeedit,1,1,1,2);
grid->addWidget(filecreatetime,2,0);
grid->addWidget(timeedit,2,1,1,2);
grid->addWidget(filemodifytime,3,0);
grid->addWidget(modifyedit,3,1,1,2);
grid->addWidget(fileusetime,4,0);
grid->addWidget(useedit,4,1,1,2);
grid->addWidget(filemanage,5,0);
hb->addWidget(file);
hb->addWidget(hiddenproperty);
hb->addWidget(readonlypower);
hb->addWidget(writeonlypower);
hb->addWidget(exepower);
vb=new QVBoxLayout(this);
vb->addLayout(grid);
vb->addLayout(hb);
vb->addWidget(getfileallproperty);
connect(openfilebtn,&QPushButton::clicked,this,&Dialog::openfile);
connect(getfileallproperty,&QPushButton::clicked,this,&Dialog::getallproperty);
}
Dialog::~Dialog() = default;
void Dialog::openfile()
{
QString file=QFileDialog::getOpenFileName(this,"打开文件","/","Files(*.*)");
pathedit->setText(file);
}
void Dialog::getallproperty()
{
QString path=pathedit->text();
QFileInfo list(path);
sizeedit->setText(QString::number(list.size()));
timeedit->setText(list.birthTime().toString());
modifyedit->setText(list.lastModified().toString());
useedit->setText(list.lastRead().toString());
file->setChecked(list.isFile());
hiddenproperty->setChecked(list.isHidden());
readonlypower->setChecked(list.isReadable());
writeonlypower->setChecked(list.isWritable());
exepower->setChecked(list.isExecutable());
}
mouseevent 鼠标事件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QMouseEvent>
//窗口状态栏
#include <QStatusBar>
#include <QImage>
#include <QMessageBox>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QLabel* showMousePointerlb,*statuslb;
void displayimage();
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
// QWidget interface
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
void MainWindow::displayimage()
{
QString path("/home/study/Pictures/图片/3.jpeg");
QLabel *imagelabel=new QLabel(this);
QImage *imag=new QImage;
imagelabel->move(20,20);
imagelabel->setFixedSize(200,200);
if(!(imag->load(path)))
{
QMessageBox::information(this,"消息","加载图片失败,请检查图片",QMessageBox::Ok|QMessageBox::Cancel);
delete imag;
return;
}
imagelabel->setPixmap(QPixmap::fromImage(*imag));
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("鼠标事件");
showMousePointerlb=new QLabel("");
showMousePointerlb->setFixedWidth(200);
statuslb=new QLabel("鼠标在当前坐标");
statuslb->setFixedWidth(200);
statusBar()->addPermanentWidget(statuslb);
statusBar()->addPermanentWidget(showMousePointerlb);
this->setMouseTracking(true);
resize(900,600);
displayimage();
}
MainWindow::~MainWindow() = default;
void MainWindow::mousePressEvent(QMouseEvent *event)
{
QString xpoint=QString::number(event->x());
QString ypoint=QString::number(event->y());
QString str="("+xpoint+","+ypoint+")";
if(event->button()==Qt::LeftButton)
{
statusBar()->showMessage("用户已按下鼠标【左键】,坐标为"+str,2000);
}
if(event->button()==Qt::RightButton)
{
statusBar()->showMessage("用户已按下鼠标【右键】,坐标为"+str,2000);
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
QString xpoint=QString::number(event->x());
QString ypoint=QString::number(event->y());
showMousePointerlb->setText("("+xpoint+","+ypoint+")");
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
QString xpoint=QString::number(event->x());
QString ypoint=QString::number(event->y());
QString str="("+xpoint+","+ypoint+")";
statusBar()->showMessage("用户以释放鼠标坐标"+str,2000);
showMousePointerlb->setText("("+xpoint+","+ypoint+")");
}
keyEvent
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QKeyEvent>
#include <QPixmap>
#include <QImage>
#include <QPen>
#include <QPalette>
#include <QPainter>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
void drawpix();
private:
QPixmap* pix;
QImage image;
int startx,starty,widths,heights,step;
// QWidget interface
protected:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *event);
};
#endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setWindowTitle("键盘操作事件");
setAutoFillBackground(true);
QPalette palet=this->palette();
palet.setColor(QPalette::Window,Qt::white);
setPalette(palet);
setMinimumSize(800,600);
setMaximumSize(800,600);
widths=size().width();
heights=size().height();
pix=new QPixmap(widths,heights);
pix->fill(Qt::white);
startx=60;
starty=60;
step=30;
image.load("/home/study/Pictures/图片/text.png");
drawpix();
resize(800,600);
}
Widget::~Widget() = default;
void Widget::drawpix()
{
pix->fill(Qt::green);
QPainter *pal=new QPainter;
QPen pen(Qt::DashDotDotLine);
for(int i=0;i<widths;i+=step)
{
pal->begin(pix);
pal->setPen(pen);
pal->drawLine(QPoint(i,0),QPoint(i,heights));
pal->end();
}
for(int j=0;j<heights;j+=step)
{
pal->begin(pix);
pal->setPen(pen);
pal->drawLine(QPoint(0,j),QPoint(widths,j));
pal->end();
}
pal->begin(pix);
pal->drawImage(QPoint(startx,starty),image);
pal->end();
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter pt;
pt.begin(this);
pt.drawPixmap(QPoint(0,0),*pix);
pt.end();
}
void Widget::keyPressEvent(QKeyEvent *event)
{
startx=startx-startx%step;
starty=starty-starty%step;
if(event->key()==Qt::Key_Left)
{
startx=(startx-step<0)?startx:startx-step;
}
if(event->key()==Qt::Key_Right)
{
startx=(startx+step+image.width()>widths)?startx:startx+step;
}
if(event->key()==Qt::Key_Up)
{
starty=(starty-step<0)?starty:starty-step;
}
if(event->key()==Qt::Key_Down)
{
starty=(starty+step+image.height()>heights)?starty:starty+step;
}
drawpix();
update();
}
事件过滤器
eventfilter
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMouseEvent>
#include <QEvent>
#include <QImage>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QLabel* lb1,*lb2,*lb3,*lbinfor;
QImage imag1,imag2,image3;
QHBoxLayout *hb;
QVBoxLayout *vb;
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
// QObject interface
public:
bool eventFilter(QObject *watched, QEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
lb1=new QLabel;
lb2=new QLabel;
lb3=new QLabel;
lbinfor=new QLabel("鼠标按键提示信息");
lbinfor->setAlignment(Qt::AlignCenter);
imag1.load("/home/study/Pictures/图片/5.jpg");
lb1->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
lb1->setPixmap(QPixmap::fromImage(imag1));
imag2.load("/home/study/Pictures/图片/6.jpg");
lb2->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
lb2->setPixmap(QPixmap::fromImage(imag2));
image3.load("/home/study/Pictures/图片/7.jpg");
lb3->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
lb3->setPixmap(QPixmap::fromImage(image3));
hb=new QHBoxLayout;
QWidget *wg=new QWidget(this);
vb=new QVBoxLayout(wg);
hb->addWidget(lb1);
hb->addWidget(lb2);
hb->addWidget(lb3);
vb->addLayout(hb);
vb->addWidget(lbinfor);
setCentralWidget(wg);
//事件过滤
lb1->installEventFilter(this);
lb2->installEventFilter(this);
lb3->installEventFilter(this);
}
MainWindow::~MainWindow() = default;
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched==lb1)
{
if(event->type()==QEvent::MouseButtonPress)
{
QMouseEvent *mouse=(QMouseEvent*)event;
if(mouse->buttons()&Qt::LeftButton)
{
lbinfor->setText("鼠标左键被按下,【左边图表】");
}
if(mouse->buttons()&Qt::MiddleButton)
{
lbinfor->setText("鼠标中键被按下,【中间图表】");
}
if(mouse->buttons()&Qt::RightButton)
{
lbinfor->setText("鼠标右键被按下,【右边图表】");
}
QTransform trans;
trans.scale(1.5,1.5);
QImage tempim=imag1.transformed(trans);
lb1->setPixmap(QPixmap::fromImage(tempim));
}
if(event->type()==QEvent::MouseButtonRelease)
{
lbinfor->setText("鼠标按钮以释放");
lb1->setPixmap(QPixmap::fromImage(imag1));
}
}
if(watched==lb2)
{
if(event->type()==QEvent::MouseButtonPress)
{
QMouseEvent *mou=(QMouseEvent*)event;
if(mou->buttons()&Qt::LeftButton)
{
lbinfor->setText("鼠标左键被按下,【左边图表】");
}
if(mou->buttons()&Qt::MiddleButton)
{
lbinfor->setText("鼠标中键被按下,【中间图表】");
}
if(mou->buttons()&Qt::RightButton)
{
lbinfor->setText("鼠标右键被按下,【右边图表】");
}
QTransform tras;
tras.scale(1.5,1.5);
QImage temp=imag2.transformed(tras);
lb2->setPixmap(QPixmap::fromImage(temp));
}
if(event->type()==QEvent::MouseButtonRelease)
{
lbinfor->setText("鼠标按钮以释放");
lb2->setPixmap(QPixmap::fromImage(imag2));
}
}
if(watched==lb3)
{
if(event->type()==QEvent::MouseButtonPress)
{
QMouseEvent *mous=(QMouseEvent*)event;
if(mous->buttons()&Qt::LeftButton)
{
lbinfor->setText("鼠标左键被按下,【左边图表】");
}
if(mous->buttons()&Qt::MiddleButton)
{
lbinfor->setText("鼠标中键被按下,【中间图表】");
}
if(mous->buttons()&Qt::RightButton)
{
lbinfor->setText("鼠标右键被按下,【右边图表】");
}
QTransform trs;
trs.scale(1.5,1.5);
QImage temp=image3.transformed(trs);
lb3->setPixmap(QPixmap::fromImage(temp));
}
if(event->type()==QEvent::MouseButtonRelease)
{
lbinfor->setText("鼠标按钮以释放");
lb3->setPixmap(QPixmap::fromImage(image3));
}
}
return QMainWindow::eventFilter(watched,event);
}
ini文件操作
#ifndef WRINI_H
#define WRINI_H
#include <QSettings>
#include <QtDebug>
void WritIniFile();
void ReadIniFile();
#endif // WRINI_H
#include "wrini.h"
void WritIniFile()
{
//使用qsetting读写ini
QSettings *set=new QSettings("MyConfig.ini",QSettings::IniFormat);
//向文件写入信息
set->setValue("MySQL/ip","127.0.0.1");
set->setValue("MySQL/port","3306");
set->setValue("MySQL/username","root");
set->setValue("MySQL/password","123");
delete set;
}
void ReadIniFile()
{
QSettings *readset=new QSettings("MyConfig.ini",QSettings::IniFormat);
QString strip=readset->value("MySQL/ip").toString();
int port=readset->value("MySQL/port").toInt();
QString strname=readset->value("MySQL/username").toString();
QString strpassw=readset->value("MySQL/password").toString();
qDebug()<<"ip地址:"<<strip.toUtf8().data()<<"\n"<<"端口号:"<<port<<"\n"<<"用户名:"<<strname.toUtf8().data()<<"\n"<<"用户密码:"<<strpassw.toUtf8().data();
delete readset;
}
#include <QCoreApplication>
#include "wrini.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//调用写入
WritIniFile();
//读取ini
ReadIniFile();
return QCoreApplication::exec();
}
json 文件读取
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QMessageBox>
#include <QFile>
//json文档
#include <QJsonDocument>
//json对象
#include <QJsonObject>
//json错误
#include <QJsonParseError>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_pushButton_clicked()
{
//创建json对象
QJsonObject MySqlJson;
MySqlJson.insert("ip","127.0.0.1");
MySqlJson.insert("port",3306);
MySqlJson.insert("user","root");
MySqlJson.insert("passw","123");
QJsonObject jsoninfo;
jsoninfo.insert("code",1);
jsoninfo.insert("mesg","数据库配置信息");
jsoninfo.insert("data",MySqlJson);
//创建文档
QJsonDocument jsondoc;
jsondoc.setObject(jsoninfo);
//写入文件中
QFile file("./jsonfile.json");
if(file.open(QIODevice::WriteOnly))
{
file.write(jsondoc.toJson());
file.close();
qDebug()<<"json写入成功";
}
QMessageBox::information(this,"信息","json写入成功");
}
void Dialog::on_pushButton_2_clicked()
{
QString strjson;
QFile files("./jsonfile.json");
if(files.open(QIODevice::ReadOnly))
{
strjson=files.readAll();
files.close();
}
QJsonParseError parseerr;
//将字符串转成json文档
QJsonDocument doc=QJsonDocument::fromJson(strjson.toUtf8(),&parseerr);
QString tem;
//判断文档是否为空以及是否转换时有无错误
if(!doc.isEmpty()&&parseerr.error==QJsonParseError::NoError)
{
//将文档转换成对象
QJsonObject json=doc.object();
QJsonValue codes=json.value("code");
QJsonValue data=json.value("data");
if(codes.isUndefined()||codes.toInt()!=1||data.isUndefined()||!data.isObject())
{
qDebug()<<"转换json数据错误,请检查";
QMessageBox::critical(this,"错误","转换json数据错误,请检查");
exit(100);
}
QJsonObject datainfo=data.toObject();
QJsonValue ip=datainfo.value("ip");
QJsonValue port=datainfo.value("port");
QJsonValue user=datainfo.value("user");
QJsonValue passw=datainfo.value("passw");
if(ip.isUndefined()||port.isUndefined()||user.isUndefined()||passw.isUndefined())
{
qDebug()<<"ip,port,user,passworld不能为空,请检查";
QMessageBox::critical(this,"错误","ip,port,user,passworld不能为空,请检查");
exit(100);
}
QString strip=ip.toString().toUtf8().data();
int ports=port.toInt();
QString struser=user.toString().toUtf8().data();
QString strpassw=passw.toString().toUtf8().data();
if(strip.isEmpty()||struser.isEmpty()||strpassw.isEmpty())
{
qDebug()<<"ip,user,passworld不能为空,请检查";
QMessageBox::critical(this,"错误","ip,user,passworld不能为空,请检查");
exit(100);
}
qDebug()<<"数据库ip:"<<strip<<"\n"<<"数据库接口:"<<ports<<"\n"<<"用户名:"<<struser<<"\n"<<"密码:"<<strpassw;
}
}
xml读取写入
- 添加额外引入在pro文件中
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
//xml
#include <QDomDocument>
#include <QDir>
#include <QFile>
#include <QDebug>#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
//xml
#include <QDomDocument>
#include <QDir>
#include <QFile>
#include <QDebug>
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
Ui::Dialog *ui;
QFile file;
QString currentpathfile;
QString currentfilename;
QDir dirs;
public:
bool openxmlfile(QString filepath);
void readxml();
void writexml();
//读取xml节点
void readrootxml(QDomNodeList nodelist);
private slots:
void on_writexmlbtn_clicked();
void on_readxmlbtn_clicked();
};
#endif // DIALOG_H
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
Ui::Dialog *ui;
QFile file;
QString currentpathfile;
QString currentfilename;
QDir dirs;
public:
bool openxmlfile(QString filepath);
void readxml();
void writexml();
//读取xml节点
void readrootxml(QDomNodeList nodelist);
private slots:
void on_writexmlbtn_clicked();
void on_readxmlbtn_clicked();
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
currentpathfile="/home/study/xmlfiles";
currentfilename="/test.xml";
}
Dialog::~Dialog()
{
delete ui;
}
bool Dialog::openxmlfile(QString filepath)
{
dirs.setPath(filepath);
if(!dirs.exists())
{
dirs.mkpath(filepath);
qDebug()<<filepath;
}
file.setFileName(filepath+currentfilename);
return file.open(QIODevice::ReadWrite|QFile::Text);
}
void Dialog::readxml()
{
if(!openxmlfile(currentpathfile))
{
qDebug()<<"读取xml文档失败";
return;
}
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
qDebug()<<"读取xml内容失败";
return;
}
//读取第一个元素节点
QDomElement rootnodel=doc.documentElement();
//获取根节点得一个元素节点(worke)
QDomNode node=rootnodel.firstChild();
while(!node.isNull())
{
//获取所有子节点元素
QDomNodeList list=node.childNodes();
//读取父节点名称
QString rootname=node.toElement().tagName();
if(rootname.compare("worke")==0)
{
readrootxml(list);
}
//读取下一个父节点
node=node.nextSibling();
}
}
void Dialog::writexml()
{
if(!openxmlfile(currentpathfile))
{
qDebug()<<"打开xml文件是失败";
return;
}
else
{
qDebug()<<"打开xml成功,请写入xml内容";
QDomDocument domdoc;
//写入xml的头部
QDomProcessingInstruction version;
//头部xml内容
version=domdoc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
//追加到xml文档中
domdoc.appendChild(version);
//创建根节点
QDomElement domel=domdoc.createElement("factory");
//
domdoc.appendChild(domel);
QDomElement itemparent=domdoc.createElement("worke");
{
//创建子节点
QDomElement node1=domdoc.createElement("WNo");
//创建文本节点
QDomText domtext1=domdoc.createTextNode("WNo");
//将输入框中内容填充到文本节点中
domtext1.setData(ui->numberid->text());
//将文本节点添加到子节点中
node1.appendChild(domtext1);
//子节点添加到父节点中
itemparent.appendChild(node1);
//创建子节点
QDomElement node2=domdoc.createElement("WName");
//创建文本节点
QDomText domtext2=domdoc.createTextNode("WName");
//将输入框中内容填充到文本节点中
domtext2.setData(ui->nameedit->text());
//将文本节点添加到子节点中
node2.appendChild(domtext2);
//子节点添加到父节点中
itemparent.appendChild(node2);
//创建子节点
QDomElement node3=domdoc.createElement("WSex");
//创建文本节点
QDomText domtext3=domdoc.createTextNode("WSex");
//将输入框中内容填充到文本节点中
domtext3.setData(ui->sexedit->text());
//将文本节点添加到子节点中
node3.appendChild(domtext3);
//子节点添加到父节点中
itemparent.appendChild(node3);
//创建子节点
QDomElement node4=domdoc.createElement("WEducation");
//创建文本节点
QDomText domtext4=domdoc.createTextNode("WEducation");
//将输入框中内容填充到文本节点中
domtext4.setData(ui->studyedit->text());
//将文本节点添加到子节点中
node4.appendChild(domtext4);
//子节点添加到父节点中
itemparent.appendChild(node4);
//创建子节点
QDomElement node5=domdoc.createElement("WDepartment");
//创建文本节点
QDomText domtext5=domdoc.createTextNode("WDepartment");
//将输入框中内容填充到文本节点中
domtext5.setData(ui->departedit->text());
//将文本节点添加到子节点中
node5.appendChild(domtext5);
//子节点添加到父节点中
itemparent.appendChild(node5);
//创建子节点
QDomElement node6=domdoc.createElement("WSalary");
//创建文本节点
QDomText domtext6=domdoc.createTextNode("WSalary");
//将输入框中内容填充到文本节点中
domtext6.setData(ui->salaryedit->text());
//将文本节点添加到子节点中
node6.appendChild(domtext6);
//子节点添加到父节点中
itemparent.appendChild(node6);
}
domel.appendChild(itemparent);
file.write(domdoc.toString().toUtf8().data());
file.close();
QMessageBox::information(this,"提示","写入xml文件成功,请在文件按中查看");
}
}
void Dialog::readrootxml(QDomNodeList nodelist)
{
for(int nod=0;nod<nodelist.size();nod++)
{
QDomElement sonel=nodelist.at(nod).toElement();
if(sonel.toElement().tagName().compare("WNo")==0&&ui->numbrerid->text().isEmpty())
{
ui->numbrerid->setText(sonel.text());
}
else if(sonel.toElement().tagName().compare("WName")==0&&ui->rnameedit->text().isEmpty())
{
ui->rnameedit->setText(sonel.text());
}
else if(sonel.toElement().tagName().compare("WSex")==0&&ui->rsexedit->text().isEmpty())
{
ui->rsexedit->setText(sonel.text());
}
else if(sonel.toElement().tagName().compare("WEducation")==0&&ui->rstudyedit->text().isEmpty())
{
ui->rstudyedit->setText(sonel.text());
}
else if(sonel.toElement().tagName().compare("WDepartment")==0&&ui->rdepartedit->text().isEmpty())
{
ui->rdepartedit->setText(sonel.text());
}
else if(sonel.toElement().tagName().compare("WSalary")==0&&ui->rsalaryedit->text().isEmpty())
{
ui->rsalaryedit->setText(sonel.text());
}
}
}
void Dialog::on_writexmlbtn_clicked()
{
writexml();
}
void Dialog::on_readxmlbtn_clicked()
{
readxml();
}
网络协议
- 需要额外添加network如
QT += widgets network
- 获取主机名称和ip
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
//主机信息
#include <QHostInfo>
//主机网络接口
#include <QNetworkInterface>
#include <QList>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
void gethostNameAndip();
void writehostinfo(const QString&);
private slots:
void on_gethostnamebtn_clicked();
void on_gethostallbtn_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::gethostNameAndip()
{
//获取主机名称
QString hostnames=QHostInfo::localHostName();
ui->hostname->setText(hostnames);
//获取主机地址
QString localipadress="";
//通过主机名称获取相应的所有主机信息
QHostInfo host=QHostInfo::fromName(hostnames);
//获取主机所有地址信息
QList<QHostAddress> listadress=host.addresses();
//判断地址是否为空
if(!listadress.isEmpty())
{
//循环遍历所有主机地址信息
foreach (QHostAddress add, listadress) {
//判断主机地址类型是否是ipv4类型
if(QAbstractSocket::IPv4Protocol==add.protocol())
{
//获得的主机信息赋值给主机地址变量并跳出循环
localipadress=add.toString();
break;
}
}
}
ui->hostip->setText(localipadress);
}
void Dialog::writehostinfo(const QString& info)
{
//QList<QString> list=info.split("\n");
QFile file("./hostinfor.txt");
if(file.open(QIODevice::WriteOnly))
{
//1.种写法存在冗余问题
/*QByteArray byte;
byte.resize(info.length());
memcpy(byte.data(),info.toUtf8().data(),info.length());
file.write(byte);
file.close();*/
file.write(info.toUtf8());
file.close();
}
}
void Dialog::on_gethostnamebtn_clicked()
{
gethostNameAndip();
}
void Dialog::on_gethostallbtn_clicked()
{
QString strTem="";
//获取主机所有网络接口列表
QList<QNetworkInterface> netlist=QNetworkInterface::allInterfaces();
foreach (QNetworkInterface intface, netlist)
{
strTem=strTem+"设备名称:"+intface.name()+"\n";
strTem=strTem+"硬件地址:"+intface.hardwareAddress()+"\n";
//获取所有ip地址
QList<QNetworkAddressEntry> entrylistaddress=intface.addressEntries();
foreach(QNetworkAddressEntry address,entrylistaddress)
{
strTem=strTem+"ip地址:"+address.ip().toString()+"\n";
strTem=strTem+"子网掩码:"+address.netmask().toString()+"\n";
strTem=strTem+"广播地址:"+address.broadcast().toString()+"\n";
}
}
writehostinfo(strTem);
QMessageBox::information(this,"主机信息",strTem,QMessageBox::Yes);
}
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QHostInfo>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
QString protocalTypeName(QAbstractSocket::NetworkLayerProtocol pro);
void LookUpHostInfor(const QHostInfo&);
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private slots:
void on_getdomainipbtn_clicked();
void on_cleaninforbtn_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->lineEdit->setText("www.baidu.com");
}
Dialog::~Dialog()
{
delete ui;
}
QString Dialog::protocalTypeName(QAbstractSocket::NetworkLayerProtocol pro)
{
switch (pro) {
case QAbstractSocket::IPv4Protocol:
return "IPv4 protocol";
break;
case QAbstractSocket::IPv6Protocol:
return "IPv6 protocol";
break;
case QAbstractSocket::AnyIPProtocol:
return "any protocol";
break;
default:
return "unknow ip protocol";
break;
}
}
void Dialog::LookUpHostInfor(const QHostInfo &hostinfo)
{
QList<QHostAddress> list=hostinfo.addresses();
foreach (QHostAddress address, list) {
ui->plaineditdomian->appendPlainText("协议类型:"+protocalTypeName(address.protocol()));
ui->plaineditdomian->appendPlainText("本地ip地址:"+address.toString());
}
}
void Dialog::on_getdomainipbtn_clicked()
{
QString hostname=ui->lineEdit->text();
ui->plaineditdomian->appendPlainText("你查询的主机信息:"+hostname);
QHostInfo::lookupHost(hostname,this,&Dialog::LookUpHostInfor);
}
void Dialog::on_cleaninforbtn_clicked()
{
ui->lineEdit->clear();
}
Tcp协议
TcpSocker
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QHostInfo>
#include <QHostAddress>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QTcpSocket* tcpsocket;
QString getlocalip();
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private slots:
void on_clientconnectserversbtn_clicked();
void on_clientdisconnectserver_clicked();
void on_sendmesbtn_clicked();
private:
Ui::MainWindow *ui;
private slots:
void connectserver();
void disconnectserver();
void socketreaddata();
// QWidget interface
protected:
void closeEvent(QCloseEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
tcpsocket=new QTcpSocket(this);
QString ip=getlocalip();
ui->clientcombox->addItem(ip);
connect(tcpsocket,&QTcpSocket::connected,this,&MainWindow::connectserver);
connect(tcpsocket,&QTcpSocket::disconnected,this,&MainWindow::disconnectserver);
connect(tcpsocket,&QTcpSocket::readyRead,this,&MainWindow::socketreaddata);
}
MainWindow::~MainWindow()
{
delete ui;
}
QString MainWindow::getlocalip()
{
QString hostname=QHostInfo::localHostName();
QHostInfo infor=QHostInfo::fromName(hostname);
QList<QHostAddress> list=infor.addresses();
QString strip="";
if(!list.isEmpty())
{
foreach (QHostAddress address, list) {
if(address.protocol()==QAbstractSocket::IPv4Protocol)
{
strip=address.toString();
break;
}
}
}
return strip;
}
void MainWindow::on_clientconnectserversbtn_clicked()
{
QString strip=ui->clientcombox->currentText();
quint16 port=ui->clientspinBox->value();
tcpsocket->connectToHost(strip,port);
}
void MainWindow::on_clientdisconnectserver_clicked()
{
if(tcpsocket->state()==QAbstractSocket::ConnectedState)
{
tcpsocket->disconnectFromHost();
}
}
void MainWindow::on_sendmesbtn_clicked()
{
QString mesg=ui->lineEdit->text();
ui->plainTextEdit->appendPlainText("[out]:"+mesg);
ui->lineEdit->clear();
QByteArray byte=mesg.toUtf8();
byte.append("\n");
tcpsocket->write(byte);
}
void MainWindow::connectserver()
{
ui->plainTextEdit->appendPlainText("****已经连接到服务器****");
ui->plainTextEdit->appendPlainText("****地址:"+tcpsocket->peerAddress().toString());
ui->plainTextEdit->appendHtml("****端口:"+QString::number(tcpsocket->peerPort()));
ui->clientconnectserversbtn->setEnabled(false);
ui->clientdisconnectserver->setEnabled(true);
}
void MainWindow::disconnectserver()
{
if(tcpsocket->state()==QAbstractSocket::UnconnectedState)
{
ui->plainTextEdit->appendPlainText("****服务器已断开****");
ui->clientconnectserversbtn->setEnabled(true);
ui->clientdisconnectserver->setEnabled(false);
}
}
void MainWindow::socketreaddata()
{
while(tcpsocket->canReadLine())
{
ui->plainTextEdit->appendPlainText("[in]:"+tcpsocket->readLine());
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(tcpsocket->state()==QAbstractSocket::ConnectedState)
{
tcpsocket->disconnectFromHost();
}
event->accept();
}
TcpServer
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//tcp服务连接,用于建立连接和传输数据
#include <QTcpServer>
//提供客户端与服务端的类
#include<QtNetwork>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui;
private:
QTcpServer *tcpservers;
QTcpSocket* tcpsockets;
QString getlocalIpAddress();
private slots:
void clientconnect();
void clientdisconnect();
void socketreaddata();
void newconnect();
void on_startbtn_clicked();
void on_stopbtn_clicked();
void on_sendmessage_clicked();
protected:
void closeEvent(QCloseEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString ips=getlocalIpAddress();
ui->ipcombox->addItem(ips);
tcpservers=new QTcpServer(this);
connect(tcpservers,&QTcpServer::newConnection,this,&MainWindow::newconnect);
}
MainWindow::~MainWindow()
{
delete ui;
}
QString MainWindow::getlocalIpAddress()
{
//获取主机名称
QString hostname=QHostInfo::localHostName();
//通过主机名称获取主机所有信息
QHostInfo hostinfo=QHostInfo::fromName(hostname);
QString ipstr="";
//获取主机所有地址
QList<QHostAddress> address=hostinfo.addresses();
if(!address.isEmpty())
{
//遍历主机地址
foreach (QHostAddress hostaddress, address) {
//判断主机地址协议类型是否ipv4协议类型
if(hostaddress.protocol()==QAbstractSocket::IPv4Protocol)
{
ipstr=hostaddress.toString();
break;
}
}
}
return ipstr;
}
void MainWindow::clientconnect()
{
ui->messsageplain->appendPlainText("****客户端socket连接*****");
ui->messsageplain->appendPlainText("****客户端连接地址"+tcpsockets->peerAddress().toString());
ui->messsageplain->appendPlainText("****客户端连接端口"+tcpsockets->peerPort());
}
void MainWindow::clientdisconnect()
{
ui->messsageplain->appendPlainText("****客户端socket断开连接*****");
tcpsockets->deleteLater();
}
void MainWindow::socketreaddata()
{
while(tcpsockets->canReadLine())
{
ui->messsageplain->appendPlainText("[in]:"+tcpsockets->readLine());
}
}
void MainWindow::newconnect()
{
tcpsockets=tcpservers->nextPendingConnection();
connect(tcpsockets,&QTcpSocket::connected,this,&MainWindow::clientconnect);
connect(tcpsockets,&QTcpSocket::disconnected,this,&MainWindow::clientdisconnect);
connect(tcpsockets,&QTcpSocket::readyRead,this,&MainWindow::socketreaddata);
//connect(tcpsockets,&QTcpSocket::stateChanged,this,[this](QAbstractSocket::SocketState state){OnSocketStateChanged(state)});
}
void MainWindow::on_startbtn_clicked()
{
QString ip=ui->ipcombox->currentText();
quint16 port=ui->portspli->value();
QHostAddress address(ip);
tcpservers->listen(address,port);
ui->messsageplain->appendPlainText("$$$开始监听$$$");
ui->messsageplain->appendPlainText("$$$服务器地址$$$:"+tcpservers->serverAddress().toString());
ui->messsageplain->appendPlainText("$$$服务器端口:$$$"+QString::number(tcpservers->serverPort()));
ui->startbtn->setEnabled(false);
ui->stopbtn->setEnabled(true);
}
void MainWindow::on_stopbtn_clicked()
{
if(tcpservers->isListening())
{
tcpservers->close();
ui->startbtn->setEnabled(true);
ui->stopbtn->setEnabled(false);
}
}
void MainWindow::on_sendmessage_clicked()
{
QString strmesg=ui->messageedit->text();
ui->messsageplain->appendPlainText("[out]:"+strmesg);
ui->messageedit->clear();
QByteArray strm=strmesg.toUtf8();
strm.append("\n");
tcpsockets->write(strm);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(tcpservers->isListening())
{
tcpservers->close();
}
event->accept();
}
udpsocket
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
#include <QtNetwork>
#include <QHostInfo>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
QUdpSocket* udpserver;
public:
QString gethostip();
private:
void connecttarget();
void disconnecttarget();
void readtargetdata();
private slots:
void on_startbtn_server_clicked();
void on_stopbtn_server_clicked();
void on_sendmessagebtn_server_clicked();
void on_broadcastbtn_server_clicked();
private:
Ui::MainWindow *ui;
// QWidget interface
protected:
void closeEvent(QCloseEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString ip=gethostip();
ui->comboBox_server->addItem(ip);
udpserver=new QUdpSocket(this);
connect(udpserver,&QUdpSocket::readyRead,this,&MainWindow::readtargetdata);
}
MainWindow::~MainWindow()
{
delete ui;
}
QString MainWindow::gethostip()
{
QString hostname=QHostInfo::localHostName();
QHostInfo hostinfo=QHostInfo::fromName(hostname);
QString strip="";
QList<QHostAddress> list=hostinfo.addresses();
if(!list.isEmpty())
{
foreach (QHostAddress address, list)
{
if(address.protocol()==QAbstractSocket::IPv4Protocol)
{
strip=address.toString();
break;
}
}
}
return strip;
}
void MainWindow::connecttarget()
{
quint16 ports=ui->spinBox_server->value();
if( udpserver->bind(ports))
{
//qDebug() << "Socket state before bind:" << udpserver->state();
ui->plainTextEdit->appendPlainText("***绑定成功!***");
ui->plainTextEdit->appendPlainText("***地址:"+QString::number(udpserver->localPort()));
ui->startbtn_server->setEnabled(false);
ui->stopbtn_server->setEnabled(true);
}
else
ui->plainTextEdit->appendPlainText("***绑定失败!***");
}
void MainWindow::disconnecttarget()
{
udpserver->abort();
ui->startbtn_server->setEnabled(true);
ui->stopbtn_server->setEnabled(false);
ui->plainTextEdit->appendPlainText("***已停止服务***");
}
void MainWindow::readtargetdata()
{
while(udpserver->hasPendingDatagrams())
{
QByteArray byte;
byte.resize(udpserver->pendingDatagramSize());
QHostAddress adr;
quint16 pport;
udpserver->readDatagram(byte.data(),byte.size(),&adr,&pport);
QString str=byte.data();
QString peer="[来自于:"+adr.toString()+":"+QString::number(pport)+"]";
ui->plainTextEdit->appendPlainText(peer+str);
}
}
void MainWindow::on_startbtn_server_clicked()
{
connecttarget();
}
void MainWindow::on_stopbtn_server_clicked()
{
disconnecttarget();
}
void MainWindow::on_sendmessagebtn_server_clicked()
{
//获取ip地址
QString targetip=ui->comboBox_server->currentText();
//将字符串转换成QhostAddress
QHostAddress hostaddress(targetip);
quint16 port=ui->spinBox_taget_server->value();
//连接目标服务器
qDebug()<<udpserver->localPort();
if(udpserver->localPort()!=port&&udpserver->peerAddress()!=hostaddress)
udpserver->bind(hostaddress,port);
//读取发送消息
QString msg=ui->lineEdit->text();
QByteArray sendm=msg.toUtf8();
//写入到udpsocket中
udpserver->writeDatagram(sendm,hostaddress,port);
ui->plainTextEdit->appendPlainText("[out]:"+msg);
ui->lineEdit->clear();
ui->lineEdit->setFocus();
}
void MainWindow::on_broadcastbtn_server_clicked()
{
quint16 targetports=ui->spinBox_taget_server->value();
QString msg=ui->lineEdit->text();
qDebug()<<udpserver->peerPort();
if(udpserver->peerPort()!=targetports)
udpserver->bind(targetports);
QByteArray broadcast=msg.toUtf8();
udpserver->writeDatagram(broadcast.data(),QHostAddress::Broadcast,targetports);
ui->plainTextEdit->appendPlainText("[broadcast]:"+msg);
ui->lineEdit->clear();
ui->lineEdit->setFocus();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(udpserver->state()==QAbstractSocket::ConnectedState)
{
udpserver->abort();
}
event->accept();
}
[!warning]
上面代码存在重复绑定问题
线程
thread
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
#include <QDebug>
class WorkThread : public QThread
{
Q_OBJECT
public:
WorkThread();
void stop();
private:
std::atomic<bool> m_run{false};
// QThread interface
protected:
void run();
};
#endif // WORKTHREAD_H
#include "workthread.h"
WorkThread::WorkThread() {}
void WorkThread::stop()
{
m_run=false;
}
void WorkThread::run()
{
m_run=true;
while(m_run)
{
for(int i=1;i<=5;i++)
{
qDebug()<<i<<i<<i<<i<<i;
}
QThread::msleep(10);
}
}
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "workthread.h"
#include <QPushButton>
#include <QHBoxLayout>
#define MAXSIZE 5
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private:
QPushButton* startbtn;
QPushButton* stopbtn;
QPushButton* exitbtn;
WorkThread* workThread[MAXSIZE];
public slots:
void onSlotStart();
void onSLotStop();
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle("线程测试班");
startbtn=new QPushButton;
startbtn->setText("开始");
stopbtn=new QPushButton("停止");
exitbtn=new QPushButton("退出");
QHBoxLayout *hb=new QHBoxLayout(this);
hb->addWidget(startbtn);
hb->addWidget(stopbtn);
hb->addWidget(exitbtn);
connect(startbtn,&QPushButton::clicked,this,&Dialog::onSlotStart);
connect(stopbtn,&QPushButton::clicked,this,&Dialog::onSLotStop);
connect(exitbtn,&QPushButton::clicked,this,&Dialog::close);
}
Dialog::~Dialog() = default;
void Dialog::onSlotStart()
{
for (int i = 0; i < MAXSIZE; i++) {
workThread[i]=new WorkThread;
}
for (int i = 0; i < MAXSIZE; i++) {
workThread[i]->start();
}
startbtn->setEnabled(false);
stopbtn->setEnabled(true);
}
void Dialog::onSLotStop()
{
for (int i = 0; i < MAXSIZE; i++) {
workThread[i]->stop();
workThread[i]->wait();
}
startbtn->setEnabled(true);
stopbtn->setEnabled(false);
}
信号量Semaphore
#include <QCoreApplication>
#include <QThread>
//信号量
#include <QSemaphore>
#include <QTime>
#include <QRandomGenerator>
#include <iostream>
const int datasize=10;
const int buffersize=1;
QSemaphore freespace(buffersize);
QSemaphore usedspace(0);
class producer:public QThread
{
protected:
void run()
{
//生成随机数
QRandomGenerator::global()->bounded(QTime(0,0,0,0).secsTo(QTime::currentTime()));
QRandomGenerator rands(NULL);
for(int i=0;i<datasize;i++)
{
//获取资源
freespace.acquire();
std::cerr<<i<<":producer->";
//释放资源
usedspace.release();
}
}
};
class consumers:public QThread
{
// QThread interface
protected:
void run()
{
for(int i=0;i<datasize;++i)
{
usedspace.acquire();
std::cerr<<i<<":consumer->";
freespace.release();
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
producer p;
consumers c;
p.start();
c.start();
p.wait();
c.wait();
return QCoreApplication::exec();
}
互斥量Mutex\Mutexlocker
#include <QCoreApplication>
#include <iostream>
//互斥量
#include <QMutex>
//
#include <QThread>
#include <QObject>
class ticketsallers:public QObject
{
public:
ticketsallers();
~ticketsallers();
public slots:
void salefn();
public:
//票数
int *tickets;
//互斥量
QMutex* metx;
//销售员名称
std::string sellername;
};
ticketsallers::ticketsallers()
{
metx=NULL;
tickets=0;
}
ticketsallers::~ticketsallers()
{
}
void ticketsallers::salefn()
{
//判断票数是否大于0
while((*tickets)>0)
{
metx->lock();
if((*tickets<=0))
{
metx->unlock();
break;
}
std::cout<<sellername<<":"<<(*tickets)--<<std::endl;
metx->unlock();
QThread::msleep(100);
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int tickets=20;
QMutex mtx;
//创建线程
QThread thread1;
ticketsallers seller1;
//设置线程
seller1.tickets=&tickets;
seller1.metx=&mtx;
seller1.sellername="张三";
//将对象移动到线程中
seller1.moveToThread(&thread1);
QThread thread2;
ticketsallers seller2;
seller2.tickets=&tickets;
seller2.metx=&mtx;
seller2.sellername="李四";
seller2.moveToThread(&thread2);
QThread thread3;
ticketsallers seller3;
seller3.tickets=&tickets;
seller3.metx=&mtx;
seller3.sellername="王五";
seller3.moveToThread(&thread3);
QObject::connect(&thread1,&QThread::started,&seller1,&ticketsallers::salefn);
QObject::connect(&thread2,&QThread::started,&seller2,&ticketsallers::salefn);
QObject::connect(&thread3,&QThread::started,&seller3,&ticketsallers::salefn);
thread1.start();
thread2.start();
thread3.start();
return QCoreApplication::exec();
}
多线程cs模拟
#ifndef HANDERTHREAD_H
#define HANDERTHREAD_H
#include <QThread>
//建立tcp连接并传输数据流
#include <QTcpSocket>
//TCP/IP客户端和服务器的类
#include <QtNetwork>
//tcp、udp发送和接收数据都是通过二进制字节数组QByteArray
#include <QByteArray>
class handerThread : public QThread
{
Q_OBJECT
public:
handerThread(int socketdescriptor,QObject *parent=nullptr);
signals:
void error(QTcpSocket::SocketError socketerror);
private:
int socketdescriptor;
// QThread interface
protected:
void run();
};
#endif // HANDERTHREAD_H
#include "handerthread.h"
handerThread::handerThread(int socketdescriptor,QObject *parent):
QThread(parent),
socketdescriptor(socketdescriptor)
{
}
void handerThread::run()
{
QTcpSocket socket;
if(!socket.setSocketDescriptor(socketdescriptor))
{
emit error(socket.error());
return;
}
QByteArray byte;
QDataStream out(&byte,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_6_5);
socket.write(byte);
socket.disconnectFromHost();
}
#ifndef CLIENTSERVER_H
#define CLIENTSERVER_H
#include <QTcpServer>
//前向声明;用于 减少编译依赖,加快编译速度
class Dialog;
#include "handerthread.h"
//第二步
class ClientServer : public QTcpServer
{
Q_OBJECT
public:
explicit ClientServer(QObject *parent = nullptr);
// QTcpServer interface
protected:
void incomingConnection(int socketdescriptor);
Dialog* dlog;
};
#endif // CLIENTSERVER_H
#include "clientserver.h"
//需要知道所有细节
#include "dialog.h"
ClientServer::ClientServer(QObject *parent)
: QTcpServer{parent}
{
dlog=(Dialog*)parent;
}
void ClientServer::incomingConnection(int socketdescriptor)
{
handerThread* thread=new handerThread(socketdescriptor,0);
//显示客户端访问次数
connect(thread,&handerThread::finished,dlog,&Dialog::showfn);
connect(thread,&handerThread::finished,thread,&handerThread::deleteLater,Qt::DirectConnection);
thread->start();
}
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QMessageBox>
class ClientServer;
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private:
Ui::Dialog *ui;
private:
int icount;
ClientServer* tcpserver;
public slots:
void showfn();
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
#include "clientserver.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
icount=0;
tcpserver=new ClientServer(this);
if(!tcpserver->listen())
{
QMessageBox::critical(this,"错误",tr("多线程服务无法启动").arg(tcpserver->errorString()));
close();
return;
}
ui->serveredit->setText(tr("%1").arg(tcpserver->serverPort()));
connect(ui->exitbtn,&QPushButton::clicked,this,&Dialog::close);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::showfn()
{
ui->countclient->setText(tr("客户端请求%1次").arg(++icount));
}
客户端
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QTcpSocket>
#include <QMessageBox>
#include <QAbstractSocket>
#include <QDataStream>
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
private:
QTcpSocket* socket;
private slots:
void on_applicatantserverbtn_clicked();
public slots:
void showError(QAbstractSocket::SocketError error);
void operatorexc();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
socket=new QTcpSocket(this);
connect(ui->applicatantserverbtn,&QPushButton::clicked,this,&Dialog::operatorexc);
connect(ui->exitbtn,&QPushButton::clicked,this,&Dialog::close);
connect(socket,&QTcpSocket::errorOccurred,this,&Dialog::showError);
ui->serverport->setFocus();
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_applicatantserverbtn_clicked()
{
ui->applicatantserverbtn->setEnabled(!ui->servername->text().isEmpty()&&ui->serverport->text().isEmpty());
}
void Dialog::showError(QAbstractSocket::SocketError error)
{
switch(error)
{
case QAbstractSocket::RemoteHostClosedError:
QMessageBox::information(this,"提示","远程主机关闭连接",QMessageBox::Yes);
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this,"提示","找不到远程主机",QMessageBox::Yes);
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this,"提示","连接主机拒绝连接(或超时)",QMessageBox::Yes);
break;
default:
QMessageBox::information(this,"错误",tr("致命错误:%1").arg(socket->errorString()));
break;
}
ui->applicatantserverbtn->setEnabled(true);
}
void Dialog::operatorexc()
{
ui->servername->setEnabled(false);
//取消已有的所有连接
socket->abort();
socket->connectToHost(ui->servername->text(),ui->serverport->text().toInt());
if(socket->state()==QAbstractSocket::ConnectedState)
{
QMessageBox::information(this,"提示","为连接成功");
}
}
[!note]
服务端run中改成 // while(socket.state()==QAbstractSocket::ConnectedState)
// {
// if(socket.waitForReadyRead(10000))
// {
// byte=socket.readAll();
// socket.write(byte);
// }
// }并注销 socket.disconnectFromHost();可以实现一直保持连接,但存在延迟,只有等待waitForReadyRead秒数结束后才能写入
Http
- 流程
- 客户端要与服务端建立连接
- 客户端要想服务器请求数据
- 服务端返回相应的数据报
- 客户端与服务端要断开连接
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//提供TCP/IP客户端和服务器类型
#include <QtNetwork>
#include <QUrl>
class QNetworkAccessManager;
//是QIODevice的子类,封装QNetworkAccessManager信息
class QNetworkReply;
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui;
QNetworkAccessManager* mgr;
private slots:
void replayFinishedfn(QNetworkReply *);
void on_getinforbtn_clicked();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
mgr=new QNetworkAccessManager(this);
connect(mgr,&QNetworkAccessManager::finished,this,&MainWindow::replayFinishedfn);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::replayFinishedfn(QNetworkReply *reply)
{
QString strall=reply->readAll();
ui->textBrowser->setText(strall);
reply->deleteLater();
}
void MainWindow::on_getinforbtn_clicked()
{
mgr->get(QNetworkRequest(QUrl("http://www.baidu.com")));
}
#ifndef MYHTTPSERVER_H
#define MYHTTPSERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QObject>
class MyHttpServer:public QObject
{
Q_OBJECT
public:
explicit MyHttpServer(QObject* parent=nullptr);
~MyHttpServer();
public:
QTcpSocket* socket;
private:
QTcpServer* tcpserver;
qint64 byteAvailable()const;
public slots:
void connect();
};
#endif // MYHTTPSERVER_H
#include "myhttpserver.h"
MyHttpServer::MyHttpServer(QObject *parent):QObject(parent)
{
tcpserver=new QTcpServer(this);
QObject::connect(tcpserver,&QTcpServer::newConnection,this,&MyHttpServer::connect);
if(!tcpserver->listen(QHostAddress::Any,8085))
{
qDebug()<<"致命错误,web服务器没有实现";
}
else
{
qDebug()<<"启动成功";
}
}
MyHttpServer::~MyHttpServer()
{
socket->close();
}
void MyHttpServer::connect()
{
socket=tcpserver->nextPendingConnection();
while(!(socket->waitForReadyRead(100)));
char webdata[1000];
int sv=socket->read(webdata,1000);
qDebug()<<"正常运行:读取信息。。"<<QString(webdata);
socket->write("HTTP/1.1 200 OK\r\n");
socket->write("Content-Type:text/html\r\n");
socket->write("Connection:close\r\n");
socket->write("Refresh:1\r\n\r\n");
socket->write("<!DOCTYPE html>"
"<html>"
"<head>"
"<meta http-equiv=\"content-Type\" content=\"text/html; charset=utf-8\">"
"<title>httpserver</title>"
"</head>"
"<body>客户端已经连接到httpserver服务器秒数为:");
QByteArray bytesary;
static qint16 icount;
bytesary.setNum(icount++);
socket->write(bytesary);
socket->write("</body></html>");
socket->flush();
QObject::connect(socket,&QTcpSocket::disconnected,socket,&QTcpSocket::deleteLater);
socket->disconnectFromHost();
}
websocket
- 需要引入websockets
websocketserver
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QAbstractSocket>
//
#include <QWebSocket>
#include <QWebSocketServer>
//读取和写入json相关方法
#include <QJsonDocument>
//json对象
#include <QJsonObject>
#include <QListWidgetItem>
//前向声明
class QWebSocket;
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
private:
Ui::Widget *ui;
class QWebSocketServer *websocketserver;
QList<QWebSocket*> websocketlist;
void getNewConnect();
void receiveMsg(const QString&);
public slots:
void onerrrofn(QAbstractSocket::SocketError error);
private slots:
void on_sendbtn_clicked();
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//ws(服务器非安全模式)
//wss (服务器安全模式)
websocketserver=new QWebSocketServer(QStringLiteral("testServer"),QWebSocketServer::NonSecureMode,this);
connect(websocketserver,&QWebSocketServer::newConnection,this,&Widget::getNewConnect);
websocketserver->listen(QHostAddress::Any,8808);
}
Widget::~Widget()
{
delete ui;
for(auto socket:websocketlist)
{
socket->close();
}
websocketserver->close();
}
void Widget::getNewConnect()
{
//判断服务器是否有挂起连接
if(websocketserver->hasPendingConnections())
{
//将挂起的下一个对象作为已连接的对象返回
QWebSocket *websockets=websocketserver->nextPendingConnection();
ui->meslistedit->append(websockets->origin()+"客户端已连接到服务器");
websocketlist<<websockets;
QListWidgetItem *items=new QListWidgetItem;
items->setText(websockets->origin());
ui->ClientlistWidget->addItem(items);
connect(websockets,&QWebSocket::disconnected,this,[websockets,this]()
{
ui->meslistedit->append(websockets->origin()+"客户端已经断开服务器");
websocketlist.removeOne(websockets);
for (int i = 0; i < ui->ClientlistWidget->count(); ++i) {
QListWidgetItem *item=ui->ClientlistWidget->item(i);
if(item->text()==websockets->origin())
{
ui->ClientlistWidget->removeItemWidget(item);
delete item;
break;
}
}
websockets->deleteLater();
});
connect(websockets,&QWebSocket::textMessageReceived,this,&Widget::receiveMsg);
connect(websockets,&QWebSocket::errorOccurred,this,&Widget::onerrrofn);
}
}
void Widget::receiveMsg(const QString &msg)
{
QJsonDocument doc=QJsonDocument::fromJson(msg.toLatin1().data());
if(doc.isNull())
{
QWebSocket *websocket=qobject_cast<QWebSocket*>(sender());
ui->meslistedit->append("接收到客户端信息["+websocket->origin()+"]-->"+msg);
}else
{
QJsonObject jdo=doc.object();
QString dst=jdo["dst:"].toString();
for(auto socket:websocketlist)
{
if(dst==socket->origin())
{
socket->sendTextMessage(msg);
}
}
}
}
void Widget::onerrrofn(QAbstractSocket::SocketError error)
{
QWebSocket *websocket=qobject_cast<QWebSocket*>(sender());
ui->meslistedit->append(websocket->origin()+"出错"+websocket->errorString());
}
void Widget::on_sendbtn_clicked()
{
QString msg=ui->sendmsgedit->toPlainText().trimmed();
if(msg.isEmpty())
{
return;
}
if(ui->sendallmsgbtn->isChecked())
{
if(websocketlist.size()==0)
{
return;
}
for(auto socket:websocketlist)
{
socket->sendTextMessage(msg);
}
ui->meslistedit->append("服务器给所有连接发送:"+msg);
}else
{
if(!ui->ClientlistWidget->currentItem())
{
return;
}
QString current=ui->ClientlistWidget->currentItem()->text();
QWebSocket *websocket=nullptr;
for(auto socket:websocketlist)
{
if(socket->origin()==current)
{
websocket=socket;
break;
}
}
if(websocket)
{
websocket->sendTextMessage(current);
ui->meslistedit->append("服务器给["+websocket->origin()+"信息]"+msg);
}
}
}
websocketclient
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QAbstractSocket>
#include <QWebSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
class QWebSocket;
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
private:
Ui::Widget *ui;
QWebSocket* websocket;
void receviedMsg(const QString&);
bool isConnect=false;
private slots:
void onErrorFn(QAbstractSocket::SocketError error);
void on_connectserverbtn_clicked();
void on_sendmsgbtn_clicked();
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
websocket=nullptr;
}
Widget::~Widget()
{
delete ui;
if(websocket)
websocket->close();
}
void Widget::receviedMsg(const QString &msg)
{
QJsonDocument doc=QJsonDocument::fromJson(msg.toLatin1().data());
if(doc.isNull())
{
ui->sendmsglistedit->append("接收消息:"+msg);
}
else
{
QJsonObject json=doc.object();
ui->sendmsglistedit->append("收到来自"+json["SRC"].toString()+"的消息:"+json["MSG"].toString());
}
}
void Widget::onErrorFn(QAbstractSocket::SocketError error)
{
ui->sendmsglistedit->append(websocket->origin()+"出错"+websocket->errorString());
}
void Widget::on_connectserverbtn_clicked()
{
if(!websocket)
{
if(ui->servernameedit->text().trimmed().isEmpty())
{
QMessageBox::information(this,"提示","服务器名称不能为空",QMessageBox::Yes);
return;
}
websocket=new QWebSocket(ui->servernameedit->text().trimmed(),QWebSocketProtocol::VersionLatest,this);
connect(websocket,&QWebSocket::connected,this,[this]
{
ui->sendmsglistedit->append("已连接上"+websocket->peerAddress().toString());
isConnect=true;
ui->connectserverbtn->setText("断开服务器");
});
connect(websocket,&QWebSocket::disconnected,this,[this]
{
ui->sendmsglistedit->append(websocket->peerAddress().toString()+"已断开连接");
isConnect=false ;
ui->connectserverbtn->setText("连接服务器");
});
connect(websocket,&QWebSocket::errorOccurred,this,&Widget::onErrorFn);
connect(websocket,&QWebSocket::textMessageReceived,this,&Widget::receviedMsg);
}
if(!isConnect)
{
websocket->open(QUrl(ui->serveraddressedit->text().trimmed()));
}
else
{
websocket->close();
websocket->deleteLater();
websocket=nullptr;
}
}
void Widget::on_sendmsgbtn_clicked()
{
if(!websocket||!websocket->isValid())
{
return;
}
QString str=ui->sendmsgedit->toPlainText().trimmed();
if(str.isEmpty())
{
return;
}
QString strclient=ui->lineEdit->text().trimmed();
if(strclient.isEmpty())
{
websocket->sendTextMessage(str);
ui->sendmsglistedit->append("发送消息:"+str);
}
else
{
QJsonObject json;
json["src"]=websocket->origin();
json["dst"]=strclient;
json["msg"]=str;
websocket->sendTextMessage(QString(QJsonDocument(json).toJson(QJsonDocument::Compact)));
ui->sendmsglistedit->append("给客户端"+strclient+"发送消息:"+str);
}
ui->sendmsgedit->clear();
}
浙公网安备 33010602011771号