1 概述
这个是仿照Win10
自带的计算器制作的简化版本,是用Qt做的,直接把整个表达式输入然后得出计算结果。
主要分为三部分:
- 界面:就是看到的计算器,包括标题栏,中间的输出框,还有各个按键
- 事件处理:就是处理对应的鼠标与键盘事件
- 表达式处理:就是处理整个输入的字符串,返回计算的结果,当然这个还支持错误判断功能
2 新建工程
选择Widgets Application
:
一般只需MinGW
:
这里默认即可,名字可以随便改。
3 界面
3.1 按键
按键的话,基本上按着改就可以了,改布局,改颜色,改字体。
首先先打开.ui文件:
3.1.1 Grid Layout
添加一个Grid Layout
并调整好大小。
3.1.2 按键
拖入Push Button
作为按键,sizePolicy
属性那里水平和垂直属性都选择Expanding
:
3.1.3 颜色与字体
调整好颜色,设置styleSheet
与字体:
参考styleSheet
如下:
border:1px groove rgb(220,220,220);
background-color:rgb(243,243,243);
字体:
3.1.4 布局
复制制作好的Button
,布好局。
3.1.5 改内容
这里不仅把里面的字符改变,还要把相应的对象名也改变:
再细调每一个按键,包括大小、字体与颜色,使总体效果更好:
数字要注意有"加粗"效果,符号的话尽量"精细"一点。
3.1.6 大小与间隔
整体修改大小,同时加上间隔。
调整好间隔,注意细节。
下面是Win10
自带的计算器:
看到间隔了没?
想要的就是这种效果。
可以先运行看看:
两边的间隔的话一会配合widget
的大小调整即可。
3.2 输出框
输出框很简单,就是一个QLineEdit
。
3.2.1 QLineEdit
首先添加一个QLineEdit
。
3.2.2 大小与颜色
调整好大小,设置好背景颜色。
參考qss
如下:
border:0px groove rgb(243,243,243);
background-color:rgb(245,245,245);
3.2.3 其他
设置字体、只读和对齐。
3.3 标题栏
标题栏其实也很简单,一个QBoxLayout
。
3.3.1 新建Horizontal Layout
3.3.2 添加细节
QLabel
输入标题,两个QPushButton
表示最小化与关闭,同时加入两个Spacer
,让标题与左边空出一些距离。
其实就是模仿Win10
的标题栏的效果。
这里就不做最大化了。因为涉及到按钮的重新排布问题,这个可以自己选择实现。
3.4 整体处理
3.4.1 标题栏
把上一步做的标题栏移到合适的位置,同时删除自带的QMenuBar
、QToolBar
、QStatusBar
。
3.4.2 细节调整
调整整体大小,同时添加透明度。
调整好后大概就那样,透明度这里选择了0.9
。
4 事件处理
4.1 光标事件
4.1.1 标题栏
4.1.1.1 拖动效果
首先把本来那个标题栏去掉。
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
再在protected
中加入鼠标监听函数:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
私有成员中加入两个QPoint
,分别表示当前窗口坐标与光标的坐标。
QPoint mousePoint;
QPoint windowPoint;
第一个函数是鼠标按下时触发的,根据event->button()
判断是否是左键,是的话获取mouse
坐标,再设置窗口坐标。
当触发第二个函数时,即先判断是否按住左键不放,使用MainWindow
的move
方法移动窗口。
event->globalPos()
获取坐标后减去原来光标的坐标得到窗口坐标的变化量,再用原坐标加上这个变化量。
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
mousePoint = event->globalPos();
windowPoint = frameGeometry().topLeft();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
move(windowPoint + event->globalPos() - mousePoint);
}
}
4.1.1.2 最小化与关闭
这里以最小化为例,关闭也一样的,改一下函数调用即可。
在最小化按钮中右键选择Go to slot
:
选择clicked()
:
添加一个最小化函数:
下面是关闭的函数:
4.1.2 按键
按键的鼠标事件包括两个:
- 光标移入与移出事件,为按键添加阴影,加深颜色等
- 单击事件,在输出框中增减对应的字符
4.1.2.1 移入与移出事件
这里的实现方式是通过事件过滤器实现的,增加一个eventFilter()
函数:
bool eventFilter(QObject *,QEvent *);
首先通过event->type()
判断事件类型,如果是光标悬停,再判断对应的各个对象增加阴影效果。
addNumButtonEffet()
如下:
void MainWindow::addNumButtonEffect(QPushButton *button,QGraphicsDropShadowEffect *shadow)
{
shadow->setEnabled(true);
button->setStyleSheet(
"border:1px groove rgb(220,220,220);"
"background-color:rgb(193,193,193);"
);
}
这里QGraphicsDropShadowEffect *shadow
事先初始化好了:
然后在添加事件过滤器:
这里可以对比一下有没有阴影的效果:
没有阴影:
加上阴影:
呃…这里可能是截图工具的问题,看不出来有多大的效果,但是直接在机器上看是有比较大的区别的,建议还是加上阴影。
4.1.2.2 单击事件
单击事件就是单击了某个按键然后用户可以在输出框中看到对应的反应。
依次选择按键,右键Go to slot
:
选择clicked()
:
然后添加处理函数,这里实现了一个添加文本与清除焦点的函数,添加文本就是对应按键被光标单击后添加到输出框。单击后会把焦点保留在这个按钮上,键盘上敲空格默认会帮你"按一次"这个按钮,因此如果不清除焦点的话,在光标单击了某个按钮,比如7,按空格就会在输出框上输出7,光标单击了8后,按空格就会在输出框上输出8。
这里添加文本时还要注意默认的起提示作用的0。
void MainWindow::appendText(const QString &s)
{
if(ui->box->text() == "0")
ui->box->setText(s);
else
ui->box->setText(ui->box->text()+s);
}
void MainWindow::appendTextAndClearFocus(QPushButton *button, const QString &s)
{
appendText(s);
button->clearFocus();
}
4.2 键盘事件
键盘事件就是主要处理各个按键按下时的阴影与输出框添加输出。
键盘事件通过以下两个函数处理:
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
第一个是按键按下时触发的,第二个是松开按键触发的。
4.2.1 添加阴影
在按键按下时添加上阴影与颜色加深效果:
通过event->key()
依次判断各个键。
键位參考。
然后添加在keyRealeseEvent()
中把对应的阴影去掉:
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2: