1-如何将窗体的标题栏状态栏工具栏去掉
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
或者
this->setWindowFlags(Qt::FramelessWindowHint);
这种窗体将无法被拖动。
解决办法
1-头文件添加两个事件,
void mouseMoveEvent(QMouseEvent *event); //鼠标移动
void mousePressEvent(QMouseEvent *ev); //鼠标单击
void Login::mouseMoveEvent(QMouseEvent *event)
{
//只允许左键拖动 持续的动作
if(event->buttons()&Qt::LeftButton) //buttons处理的是长事件,button处理的是短暂的事件
{
//窗口跟随鼠标移动
//窗口的新位置=鼠标当前位置-差值
move(event->globalPos()-m_pt);
}
}
void Login::mousePressEvent(QMouseEvent *ev)
{
// 如果鼠标左键按下 单击
if(ev->button()&Qt::LeftButton)
{
//求差值=鼠标当前位置-窗口左上角点
m_pt=ev->globalPos()-this->geometry().topLeft(); //geometry()是矩形窗口,topLeft()是左上角的信息。
}
}
2-添加三个事件
#include <QMouseEvent>
protected:
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
private:
QPoint last;
//可以在构造函数中初始一下last变量用其成员函数setX,setY就是了
//接下来就是对三个鼠标事件的重写
void login::mousePressEvent(QMouseEvent *e)
{
last = e->globalPos();
}
void login::mouseMoveEvent(QMouseEvent *e)
{
int dx = e->globalX() - last.x();
int dy = e->globalY() - last.y();
last = e->globalPos();
move(x()+dx, y()+dy);
}
void login::mouseReleaseEvent(QMouseEvent *e)
{
int dx = e->globalX() - last.x();
int dy = e->globalY() - last.y();
move(x()+dx, y()+dy);
}
2-如何给背景添加图片,要求图片不会拉伸。自动缩放
// 设置背景图片
setAutoFillBackground(true); // 这句要加上, 否则可能显示不出背景图.
QPalette palette = this->palette();
// QResource::registerResource(":/res/index.jpg");//这个是图片的存放位置
palette.setBrush(QPalette::Window,
QBrush(QPixmap(":/res/index.jpg").scaled( // 缩放背景图.
this->size(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation))); // 使用平滑的缩放方式
this->setPalette(palette);
3-如何给控件设置样式
QString str4=QString("QPushButton{font: 12pt Agency FB;font: 12pt 华文彩云; background-color: rgb(127, 140, 141);}"
"QPushButton:hover{font: 12pt Agency FB;font: 12pt 华文彩云; background-color: rgb(255, 170, 0);}");
ui->Login_2->setStyleSheet(str4);
注意:之前在ui 界面设置的样式,会被我们使用qss的样式覆盖掉. 设置hover属性时,之前的属性应该用qss写在和hover属性同一个字符串中,而且若想保留部分的旧有样式,那旧有样式也要在hover重写
(这样能避免被qss覆盖旧有属性)
给lineEdit 设置样式时.字体样式要单独设置.(搞不清楚)
QString str3=QString(""
"QLineEdit:hover{ font: 14pt 微软雅黑; }"
"QLineEdit:hover{ font: 14pt 微软雅黑; background-color: #34495e; color:white;}");
ui->admin_searchbox->setStyleSheet(str3);
ui->admin_searchbox->setFont( QFont("微软雅黑" ,14 ));//不加上这个没法设置文字属性
4-Qt怎么连接数据库
当连接类型是sqllite时
头文件包含
#include< QSqlDatabase>
private:
QSqlDatabase m_db;
.cpp文件
//这是sqllite的操作语句
//不存在相关驱动就加载
if (QSqlDatabase::drivers().isEmpty())
QMessageBox::information(nullptr, tr("No database drivers found"),
tr("This demo requires at least one Qt database driver. "
"Please check the documentation how to build the "
"Qt SQL plugins."));
m_db = QSqlDatabase::addDatabase("QSQLITE");//这里的m_db是我在头文件创建的数据库对象
#if 0//应用程序的输出目录,以后发布时,把数据库db文件放同级目录就行
auto str= QCoreApplication::applicationDirPath()+="data.db";
qDebug()<<str;
#endif
m_db.setDatabaseName("C:\\Users\\X-SHELL-GOOGLE\\Desktop\\Data\\data.db");
//这个是数据库的存放位置
if (!m_db.open())
QMessageBox::warning(nullptr, tr("Unable to open database"), tr("An error occurred while "));
};
若选择的为mysql
#if 1
QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");
//数据库连接所需要设置的信息
db.setHostName("127.0.0.1");//
db.setDatabaseName("stu_sys");//数据库名字
db.setUserName("root");//数据库用户名
db.setPassword("root");//数据库密码
db.setPort(3306);//数据库端口号
//连接数据库
bool ok=db.open();
if(ok)
{
qDebug()<<"success";
}
else {
qDebug()<<"fail!";
}
#endif
注意:
但注意,mysql数据库是非文件型数据库。也就是你没法找到他的数据库文件进行向sqllite 那样直接用数据库文件的相对路径直接使用数据库(后面有)
请问,qt连接MySQL数据库用的setdatabaseName怎么使用mysql数据库名字的相对路径( 找不到mysql数据库文件相对的路径 )
mysql只需要知道 数据库名称,用户名,密码,就行,不需要知道库文件在哪。mysql是一个服务,它隔离了文件与用户请求。
即使是你访问本机,也只能用localhost 或127.0.0.1通过网络接口,它只有网络接口
那别的电脑要使用怎么办
我这个数据库不在他电脑上
mysql数据库怎么迁移到另一台电脑
导出成sql文件,另一台电脑导入
本地使用的话不装数据库,就换成sqllite了
若采用云数据库(mysql为例)
你将得到以下
申请成功
数据库名称:stu_sys
数据库用户:rootroot
数据库密码:b7775733c7d1b39d
数据库地址:mysql.sqlpub.com:3306
注册邮箱:2278135632@qq.com
打开这个mysql数据库的方式(控制台为例)
mysql -h 主机IP -u 用户名 -p密码
在qt中连接这个数据库的代码(这里的主机ip可以是域名,域名会解析为ip)
#if 0
QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");
//数据库连接所需要设置的信息
db.setHostName("mysql.sqlpub.com");//填申请到的域名,自动解析ip
db.setDatabaseName("stu_sys");//数据库名字
db.setUserName("rootroot");//数据库用户名
db.setPassword("b7775733c7d1b39d");//数据库密码
db.setPort(3306);//数据库端口号
//连接数据库
bool ok=db.open();
if(ok)
{
qDebug()<<"success";
}
else {
qDebug()<<"fail!";
}
#endif
5-在Qt中如何使用数据库的sql语句
以增加操作为例子
bool stuSql::addStu(stuInfo &info)//函数之前在stusql.h中定义
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句//m_db是在连接数据库时候就创建的数据库对象
//注意字符串字段加引号
QString strSql=QString ("insert into student values(null,'%1',%2,%3,%4,%5,'%6','%7')")
.arg(info.name).
arg(info.age).
arg(info.grade).arg(info.m_Class).arg(info.studentid).arg(info.phone).arg(info.wechat);
//QString的参数可以用%数字代替. 这里有一个null,表明这里是一个主键,他的维护由数据库负责.
sql.exec(strSql);// 在这里可以使用auto ret =sql.exec(strSql); 通过返回值来判断sql语句是否使用成功,如果成功就会返回true.
return 0;
}
判断数据库的语句是否执行成功
以删除的函数为例
头文件包含
#include<QError>
bool stuSql::delUser(int& id)
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
sql.exec(QString("delete from username where id='%1' ").arg(id));
// return sql.next();
QSqlError e=sql.lastError();
if(e.isValid())
{
qDebug()<<"343行 stusql delUser "<<e;
}
return 0;
}
当对数据库的成员执行select*from table等选择操作时,应该使用这样的while结构
QList<UserInfo> stuSql::getAllUser()
{
QList<UserInfo> L;
UserInfo m_Info;//这里的UserInfo是一个结构体类型
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
sql.exec("select * from usename");
while (sql.next()) {
m_Info.username= sql.value(0).toString();
m_Info.password = sql.value(1).toString();
m_Info.aut= sql.value(2).toString();
L.push_back(m_Info);
}
return L;
};
quint32 stuSql::getStuCnt()
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
sql.exec("select count(id) from student"); //sql.exec("select * from student");
quint32 uicnt=0;
while (sql.next()) {
uicnt= sql.value(0).toUInt();//打印人数
}
// qDebug()<<uicnt;打印总人数
return uicnt;
}
bool stuSql::isExist(QString strUser) //只是检索用户
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
sql.exec(QString("select*from username where username='%1' ").arg(strUser));
return sql.next();
/*
如果无法检索到该记录,则结果将放在最后一条记录之后,并返回 false。如果成功检索到记录,则返回 true。\
*/
}
关于 sql.next() 解释
next()方法的作用:指针指向下一条记录,有记录(有值)返回true并把记录内容存入到对应的对象中,也就是obj.next()的obj中。如果没有返回false。
2、.next()方法的应用:一般和ResultSet对象和while循环一起使用,去迭代结果集,并在循环中调用getXXX(intfieldIndex)/getXXX(String columnName)方法获取字段值。
过程:ResultSet对象具有指向其当前数据行的指针。开始,指针被置于第一行。
.next()方法将指针移动到下一行,然后while循环迭代遍历ResultSet对象。
while (obj.next()) {undefined
}
光标移动到下一行数据,有值(数据)返回true并迭代遍历,没有值,说明表中的行数已经走完,所以返回false退出循环。
6-给label增加点击事件.(默认Qlabel是不提供点击事件的)
头文件增加
bool eventFilter(QObject *obj,QEvent *event);//声名使用过滤器 //myLabel加上点击效果
.cpp文件
ui->myLabel->installEventFilter(this); //给控件安装事件过滤器
bool dlgAdmin::eventFilter(QObject *obj, QEvent *event)
{
//判断对象是否为myButton
if(obj == ui->myLabel-)
{
//判断事件类型是否为鼠标事件
if(event->type() == QEvent::MouseButtonPress)
{
//转换为鼠标事件
QMouseEvent *mouseenevt = static_cast<QMouseEvent*>(event);
//判断鼠标左键点击
if(mouseenevt->button() == Qt::LeftButton)
{ qDebug()<<"label被点击";
//emit apply_admin(); //发送一个信号
}
}
}
return false;
}
7-给多个按钮绑定多个不同的事件
头文件添加
bool eventFilter(QObject *target, QEvent *e);
.cpp文件添加
bool MainWindow::eventFilter(QObject *target, QEvent *e) //前面要注册事件监听.给按钮控件注册的
{
if(target == ui->deleteone)//按钮 deleteone的事件
{
if(e->type() == QEvent::MouseButtonDblClick) //双击事件
{
qDebug()<<"deleteone双击";
}
else if(e->type() == QEvent::QEvent::MouseButtonPress)//单击事件
{
qDebug()<<"deleteone单击";
}
}
else if(target == ui->delete_2) //按钮delete_2的事件
{
if(e->type() == QEvent::MouseButtonDblClick) //双击事件
{
qDebug()<<"delete_2双击";
}
else if(e->type() == QEvent::QEvent::MouseButtonPress)//单击事件
{
qDebug()<<"delete_2单击";
}
}
return 0;
}
8-选中 tablewidget 的任意行,进行删除操作
.cpp文件中
OnDelete(ui->tableWidget);//传入你要删除的任意行的那个表
void MainWindow:: OnDelete(QTableWidget* pTable)
{
if (!pTable)
{
return;
}
std::vector<int> vecItemIndex;//保存选中行的行号
QList<QTableWidgetItem*> selections = pTable->selectedItems();
for (int i = 0; i < selections.size(); i++)
{
vecItemIndex.push_back(selections.at(i)->row());//存储选中的行
//qDebug()<<selections.at(i)->row();
}
sort(vecItemIndex.rbegin(), vecItemIndex.rend());
vecItemIndex.erase(std::unique(vecItemIndex.begin(), vecItemIndex.end()), vecItemIndex.end());//去除重复的行号
//vecItemindex就存放着得到的行号
int number =0 ;
for (unsigned int k = 0 ; k < vecItemIndex.size(); k++)
{
number=vecItemIndex[k];//存放获取到的id
int id= ui->tableWidget->item(number,1)->text().toUInt();
m_ptrStuSql->delStu(id);//调用m_ptrStuSql的delStu函数
}
}
bool stuSql::delStu(int id)
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
//注意字符串字段加引号
auto ret= sql.exec(QString ("delete from username where id=%1").arg(id));
qDebug()<<ret;
return 0;
}
9-防止删除表的时候id不会清零,重新开始计数
void stuSql::clearStuTab()
{
QSqlQuery sql(m_db);//执行sqllite语句前必须使用此句
sql.exec(QString("delete from student "));
sql.exec("DELETE FROM sqlite_sequence WHERE name='student'");//删除id自增
}
10-选中tableWidget的任意一行,获取一行信息
头文件
void show_prodcut_sets(int i,int col)
.cpp文件
connect(ui->tableWidget,SIGNAL(cellClicked(int,int)),this,SLOT(show_prodcut_sets(int,int)));
.cpp文件
void MainWindow::show_prodcut_sets(int i,int col)
{
qDebug() << "所点击的单元格的row=" << i << ",col=" << col;//获取到了选中的行号和列号,我们只要行号
// 获取所点击的单元格
//学生信息部分(管理员才能看所有学生)
ui->stuName->setText( ui->tableWidget->item(i,2)->text());
ui->stuGrade->setText( (ui->tableWidget->item(i,4)->text()));
ui->stuiWechat->setText( ui->tableWidget->item(i,8)->text());
ui->stuAge->setText( ui->tableWidget->item(i,3)->text());
ui->stuScore->setText( ui->tableWidget->item(i,6)->text());
ui->stiuphone->setText( ui->tableWidget->item(i,7)->text());
ui->stiuId->setText( ui->tableWidget->item(i,1)->text());
ui->stiuClass->setText( ui->tableWidget->item(i,5)->text());
QTableWidgetItem* item = ui->tableWidget->item(i ,col);
qDebug() << item->text();
}