前段时间连续学了一个半月的邵发Qt视频,学习的过程中做了笔记,以方便自己以后用的时候查看关键点。
将之放到网盘上,以供需要的朋友。
http://pan.baidu.com/s/1c2pwN8s
Chapter1 坐标的概念
每个窗体在屏幕的显示的位置是以左上角(top-left)的相对位置来定义的。左上角的坐标为(0,0),屏幕的长边为x轴,短边为y轴。
几乎每个窗体都有一个重构的函数setGeometry(x,y, length, width)。其中x,y就是坐标系。注意此函数的的坐标的位置是不带边框的,只是现实窗体的位置。
move(x,y)函数则可以设定带边框的坐标。
Chapter2 定义自己的窗体
2.1Q_OBJECT
定义窗口类的时候一定要在头文件里面加上Q_OBJECT。
2.2勿忘父窗口
创建子控件的时候要指定父窗口(QWidget*parent)。
3.3子控件的指针不需要手动delete
构造函数在new子窗口后,不用手动delete,由父窗口来管理。
3.4手动创建窗口的缺点
比较麻烦,不能自动调动窗口。
Chapter3 窗口布局(layout)
3.1QLayout布局器
其子类为QBoxLayout,又派生了QVBoxLayout和QHBoxLayout。
3.2添加QLineEdit和QPlainTextEdit窗体
addWidget(obj);
3.3QPlainTextEdit随父窗口的变动而变动,体现了灵活性。
这是有Policy(策略)来决定的。
3.4设置布局器
Qwidget::setLayout(layout);来实现的
Chapter4 Policy窗口调整的策略
Fixed
使用sizeHint的大小,不能更大,也不能更小。
Preferred
优先使用sizeHint,可大可小。
Expanding
使用sizeHint,越大越好。
获取policy的方法
QSizePolicyQwidget::sizePolicy() const;
设置policy的方法
void QsizePolicy::setSizePolicy(QSizePolicy);
对于纵向布局,我们只关注其高度和纵向policy。
Chapter5 手工布局
<span style="font-family:SimSun;">MyWin::MyWin(QWidget *parent)
: QWidget(parent)
{
m_lineEdit = new QLineEdit(this);
m_textEdit = new QPlainTextEdit(this);
m_button = new QPushButton(this);
m_button->setText("Ok");
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(m_lineEdit);
hLayout->addWidget(m_button);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
vLayout->addWidget(m_textEdit);
this->setLayout(vLayout);
}</span>
局部变量hLayout,vLayout都叫父窗口管理(Qt)了,不用手动delete。
Chapter6 可视化布局
QtDesigner工具来布局,最后一个控件不需要添加上去,只用点击布局就好。
Chapter7 stretch factor拉伸因子
Qt自动拉伸的时候,可以控制拉伸的因子。
在用QtDisigner的时候,文本框的右边选中属性框中的sizePolicy,设置HorizontalStretch和VerticalStretch中的值。对于同一属性,如果是两个文本框,一个为1,一个为3,则在父框口变动的时候,这两个框口相应的边会按照比例来拉伸。
最大值最小值的设置。
minimumSize和maximumSize。注意和策略QSizePolicy::Maximum的区别,这是一个策略,以sizeHint为最大值,而minimumSize和maximumSize是一个属性,最大的范围。
Chapter8 Qt的事件处理
一个动作所对应的反应,就是事件处理。
SIGNAL和SLOT。SLOT插槽的意思。
VS不能识别ui文件的解决,打开自动生成的ui的头文件,点击VAssistX--〉tools→ Reparse CurrentFile。
Chapter9 QCheckBox
qDebug可以在debug模式下,打印调试信息。
signal:
void stateChanged(int state);
Displaywidgets中TextBrowser的用法,用于显示一堆文本数据。
Chapter10 QLineEdit
echoMode密码模式
echoMode输入模式– 如果是密码则选择password,这样在输入密码的时候,会以加密的形式显示。对应的是normal,这个则显示明码。
placeholderText:
行编辑空白处的提示字符。
文本内容的获取:
QString QlineEdit::text();
QMessageBox消息窗口:
当我们输入密码的时候,密码输入完毕后,点击确定,弹出密码正确或者错误的窗口。
头文件:QMessageBox,用法:QMessageBox::information(this,“title”, “message content”);
Chapter11Q ComboBox
如图:
手动创建
手动创建项目,QComboBox::addItem(“string”)和insertItem(index,“string”);
以上index是下拉框从0开始上往下数的序号。
<span style="font-family:SimSun;"> ui.cmboxLang->addItem("Chi", "ch");
ui.cmboxLang->addItem("Eng", "en");
ui.cmboxLang->addItem("Fre", "fr");
ui.cmboxLang->insertItem(2, "Kor", "ko");</span>
关联数据
QVariant &user。在addItem,insertItem的时候,最后一个参数是默认的,当显式传递参数的时候,则为组合框关联的数据。
如上代码示例中的ch,en,fr,ko。
editable属性
QComboBox的第一个私有的属性就是editable,当选中它的时候,组合框里面是可以输入数据的,点击回车的时候,新添一个item。
如图变为editable后的效果:
获取当前项的文本
QString value=ui.cmboxLang->currentText();
当手动输入其他字符的时候,当前项的文本会变成输入的字符。可是currentItem中的字符,还是之前没有输入字符时候的里面的默认值。
Chpater12 QToolButton
如图(没有设置图标和文本的样式):
icon最好选择png格式的,因为它是背景透明的。
加上icon以及文本后的效果:
toolButtonStyle(文本在icon下面)
autoRaise(浮动)模式
私有属性autoRaise,表示浮动模式的意思。浮动模式的意思是当鼠标不在此控件上面的时候,没有外边框,当鼠标在控件上(选上的时候)显示外边框。如下图鼠标不在控件上:
signaltoggled
toggled信号只在checkable的button按下去后才产生,参考“Thissignal is emitted whenever a checkable button changes its state.”
Chapter13 QLabel
原生态的QLabel
设置背景色和前景色
右键点击QLabel后,选择“ChangeStyleSheet”,color是前景色,backgroud-color是背景色。如下图:
换行模式(wordWrap)
将此属性选上后,label一次显示不了那么多的文字,则自动换行,如下图:
给label加外边框(QFrame--> frameShape --> Box)
显示图片
收藏资源,ResourceBrowser --> EditResource -->选择已经下载好的图片,添加进去。
在属性pixmap上,选择收藏好的jpg图片。如果图片太大了,此时我们要缩放图片。
图片的缩放,使之自动适应label的大小(scaleContents)
选中scaleContents。
Chapter14 字符集
Latin字符集
中文字符集
GB2312中文简体国标码(汉字数:6763),有局限性,有些生僻字不能显示。
GBK扩展中文GB编码(兼容GB2312)。更通用,因为范围广。
BIG5中文繁体字符集。
CJK中日韩大字符集。
Unicode统一码,映射全球各国的文字。
第一种方案:UTF-32。太浪费空间。
第二种方案:UTF-16。1~2个short来表示。(unicode没有注明,则为UTF-16)。
第三种方案:UTF-8。1~4个字节来表示一个字符。
字符集间的转换
每种字符集在特定的平台下都有系统API函数来相互转换的。如windows下,将GBK转化为unicode(UTF-16)的函数MultiByteToWideChar。
Chapter15 QString
VC文件数据存储的格式
VC编辑器中代码的存储在中文windows下是以GBK的形式存在的。这句话的意味着,在qstring_st.cpp中如下的代码,里面的字符都是GBK的编码形式。其中英文部分是和unicode完全兼容的,但是汉字却不同。如下的“你好,中国!”,如果直接赋值给QString的对象str,会有问题。原因是QString类是以unicode的编码形式来输出的。
<span style="font-family:SimSun;">int QString_st::OnBtnTest()
{
//QString str = "Hi, China!";
QString str = "你好,中国!"; // 这样显示会出现乱码。
ui.lineEdit->setText(str);
return 0;
}</span>
GBK字符串转换成QString对象
QStringQString::fromLocal8Bit ( const char *str,intsize=-1 )[static]
如下实例:
QStringstr=QString::fromLocal8Bit("你好,中国!");
fromLocal8Bit的缺陷
在windows下loacl8Bit是GBK,linux下local8Bit是UTF-8,所以上述转换的函数并不保险。考虑到跨平台的方面,需要其他的方法。
跨平台的处理方法
<span style="font-family:SimSun;"> QString test = ui.lineEdit->text();
QByteArray bytes = test.toUtf8();
const char *utf8 = bytes.data();
int size = bytes.size();</span>
Chapter16 QDialog对话框
模式对话框
占用整个窗口,只能操作对话框里面的选项,其他地方不能操作的对话框。在生成QDialog对象后,默认的模式就是模式对话框。
非模式对话框
除了弹出的窗口可以设置以外,其他的界面亦可以操作的对话框。
新建对话框类的时候要选定父类是QDialog。
对话框的生成(弹出)
执行函数intQDialog::exec ()后就会弹出对话框。
exec()执行后,程序会阻塞,直到调用accept()函数或者reject()函数。如下所示:
<span style="font-family:SimSun;"> #include <QDebug> // qDebug()需要的头文件。
...
LoginDlg *dlg = new LoginDlg(this);
int ret = dlg->exec(); // 显示对话框,程序阻塞。直到accept()或者reject()函数调用。
if (ret == QDialog::Accepted)
{
qDebug() << dlg->m_user << dlg->m_password;
qDebug() << "accept()";
}
else if ( ret == QDialog::Rejected )
{
qDebug() << "reject()";
}</span>
对话框标题栏的设置
先选中对话框对象,如下图所示:
然后在QWidget属性下设置windowTitle属性,如下图:
Chapter17 文件对话框
QFileDialog类实现文件对话框
一般最常用的是此类的静态函数QFileDialog::getOpenFileName和QFileDialog::getSaveFileName。当这两个函数被调用的时候会弹出相应的对话框,如下图打开对话框(保存对话框类似):
QFileDialog::getOpenFileName函数的使用
<span style="font-family:SimSun;">int QFileDialog_st::OnBtnOpen()
{
QString filename = QFileDialog::getOpenFileName(this, GBK::ToUnicode("请选择一个文件"));
if (filename.length() > 0) // 选择了要打开的文件
{
string gbkName = GBK::FromUnicode(filename);
FILE *fp = fopen(gbkName.c_str(), "rb");
fseek(fp, 0, SEEK_END);
int filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = new char[filesize + 1];
//int n = fread(buf, filesize, 1, fp);
int n = fread(buf, 1, filesize, fp);
if (n > 0)
{
buf[n] = 0;
ui.plainTextEdit->setPlainText(GBK::ToUnicode(buf));
}
delete [] buf;
fclose(fp);
}
return 0;
}</span>
QFileDialog::getSaveFileName函数的使用
<span style="font-family:SimSun;">int QFileDialog_st::OnBtnSave()
{
QString filename = QFileDialog::getSaveFileName(this, GBK::ToUnicode("保存一下"));
if (filename.length() > 0) // 选择了要保存的文件
{
string gbkName = GBK::FromUnicode(filename);
FILE *fp = fopen(gbkName.c_str(), "wb");
QString qstr = ui.plainTextEdit->toPlainText();
string cstr = GBK::FromUnicode(qstr);
fwrite(cstr.c_str(), 1, cstr.length(), fp);
fclose(fp);
}
return 0;
}
</span>
Chapter18 定时器
定时器的使用分为两步走
1,重载虚函数void QObject::timerEvent (QTimerEvent*event)[virtualprotected]
重新定义timerEvent函数是作为时间超时后的总处理函数。如下:
<span style="font-family:SimSun;">#include <QTime>
void TimerInQt::timerEvent(QTimerEvent *event)
{
//qDebug() << event->timerId();
if (event->timerId() == m_timerid)
{
QTime now = Qtime::currentTime(); // 获取当前的时间
QString text = now.toString("hh:mm:ss");
qDebug() << text;
ui.labelTime->setText(text);
}
}</span>
2,创建并开始定时器。int QObject::startTimer ( int interval)
上述函数用于创建并开始定时器,其返回值就是创建的定时器的id,其参数是每隔多少毫秒触发一次timerEvent事件,事件触发后会调用timerEvent函数。
注意timerEvent函数不能够占用太久的时间,否则会阻塞其他事件的处理,如鼠标点击控件,退出界面,输入字符等等。
timerEvent并不是线程,它是界面处理线程轮询事件标记后的函数调用。
Chapter19 多线程
设计自己的线程
1,定义一个类,继承于QThread。如下:
<span style="font-family:SimSun;">#include <QThread>
class sendTask : public QThread
{
Q_OBJECT
public:
sendTask(QObject *parent);
~sendTask();
int getStatus();
int getProcess();
int beginTask(const char *filename);
void DestroyThread(void);
private:
// 线程的总入口函数。
void run();
private:
char m_filepath[128];
int m_filesz;
int m_bytesread;
int m_status;
};</span>
2,重载线程入口函数:void run()。
3,开启线程的函数:start()。继承自QThread,此函数可直接调用。
4,线程回收:wait()。继承自QThread,此函数可直接调用。
补充知识 processBar(QProcessBar)
这个小控件可以显示进度条,如下所示:
Chapter20 容器
QTabWidget
原始模样的它:
用可视化布局的方式实现选项卡很简单。在QtDesigner里面点击Container->TabWidget->拖放到图形设计器里,设置下它的属性currentTabText和currentTabName。如下:
然后随意添加我们所需要的其他控件,我在第一个选项卡里面添加了一个lineEdit,第二个选项卡里添加了checkBox和一个pushButton。就成了如下的样子:
每个页面子控件的使用。在F7过后,上图ui会被自动生成相关代码。lineEdit和checkBox以及pushButton,会被生成这个ui的成员变量,只要用ui.xxx就可以直接调用了,如下所示:
<span style="font-family:SimSun;"> QString str = ui.lineEdit->text();
bool status = ui.checkBox->isChecked();</span>
QStackedWidget
原始模样的StackWidget
当生成一个原始模样的StackWidget的时候,我被它丑陋的外表所震惊了。什么都没有,只是在右上角的地方有两个黑色的小箭头。这个能干什么?
在其属性窗口里可以看到,它只有索引和名字,当可视化布局的时候,默认StackWidget有两页。右上角的箭头就是切换第0页和第1页的。
可见这个小控件提供的只是一个显示,两个页面重叠在一起,所以用stackwidget来命名。要想控制这两个页面,必须有两个按钮。在设计器里面添加两个按钮后,变成如下模样:
如上所说,这个默认的stackwidget有两个页面,显示哪个页面则需要专
用的函数,QStackedWidget::setCurrentIndex就是干这个事的。如下两个slot函数:
<span style="font-family:SimSun;">int QStackWidget_st::OnPage1()
{
ui.stackedWidget->setCurrentIndex(0);
return 0;
}
int QStackWidget_st::OnPage2()
{
ui.stackedWidget->setCurrentIndex(1);
return 0;
}</span>
Chapter21 QMainWindow
QMainWindow的外表
QMainWindow对象以及继承于它的对象,有一个显著的特点,那就是有菜单栏和工具栏。在qt助手里,我找到了QMainWindow对象的粗线条的描绘图,如下:
创建一个类继承于QMainWindow,得到一个原生态的界面如下(红色的注视是表明每个子窗体的名字):
添加QAction
一个QMainWindow没有action就什么都干不了。当在菜单栏里面添加一个action后,点击那个action就会做相应的动作。
1,下载相关的actionicon。
推荐网站:http://www.easyicon.net/。在搜索栏里面输入save等,得到海量的icon,选择一个我们喜欢的风格,点击它。接着又有很多像素选择给我们选,一般都是选择24PX或者16PX的png格式的。将下载好的icon放入到项目的Resources目录下。
2,将下载好的icon添加进工程。
点击QtDesigner右下角的ResourceBrowser,进入EditResource对话框,然后单击如下圈中的图标:
3,添加QAction
点击右下角的ActionEdit,然后点击New工具,弹出Newaction对话框。
4,将编辑好的action放入菜单栏,或者工具栏里。
直接将编辑好的action左键单击选中后,拖到工具栏的TypeHere处,然后松掉鼠标。就添加成功了一个action,在代码里面用action的方法是直接ui.actionxxx,如上图的action,调用的方法是ui.actionHelp。
添加action的事件处理函数(slot)
构造函数添加connect
<span style="font-family:SimSun;"> connect(ui.actionNew, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionNew()));
connect(ui.actionOpen, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionOpen()));
connect(ui.actionSave, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionSave()));</span>
slot函数的实现
<span style="font-family:SimSun;">int QMainWindow_st::OnActionNew()
{
<span style="white-space:pre"> </span>// add your codes
return 0;
}
int QMainWindow_st::OnActionOpen()
{
<pre name="code" class="html" style="color: rgb(1, 0, 1); font-size: 13.3333px;"><span> </span>// add your codes</span>
return 0;}int QMainWindow_st::OnActionSave(){<span style="font-family:SimSun;"><span> </span>// add your codes</span>
return 0;}
Chapter22 自定义控件
1,绘制窗口
1.1添加类
添加类Qt4Class而非Qt4GuiClass,选择父类为QWidget或者QFrame。一般选择QFrame。
1.2重载虚函数paintEvent,其原型为:
void QFrame::paintEvent (QPaintEvent*)[virtualprotected]
paintEvent是继承于QWidget类的一个虚函数,它是一个事件处理函数,当子类定义了后自动调用。在子类头文件里面声明:
<span style="font-family:SimSun;">class CircleWindow : public QFrame
{
Q_OBJECT
public:
CircleWindow(QWidget *parent);
~CircleWindow();
private:
void paintEvent(QPaintEvent *event); // 声明paintEvent虚函数。
};
添加定义:
void CircleWindow::paintEvent(QPaintEvent *event)
{
QPainter *painter = new QPainter(this);
int w = this->width();
int h = this->height();
painter->setBrush(QBrush(QColor(0, 0xff, 0)));
painter->drawEllipse(0, 0, w, h);
}</span>
1.3将自己定义的类CircleWindow作为控件添加到QtDesigner中。
1.3.1首先添加控件QFrame
1.3.2在QFrame里面加入自己的控件(自己定义的QFrame类)
在添加的QFrame上右键单击,在弹出的框口上点击“PrototedWidgets...”,弹出如下对话框
输入类名和头文件后,点击Add。
将刚才添加的控件后面的选项框勾上。然后点击Promote。
输入类名和头文件后,点击Add。
将刚才添加的控件后面的选项框勾上。然后点击Promote。