This post was last edited by DDZZ669 on 2022-8-7 15:55
Previous article: Embedded Qt - Write and run your first ARM-Qt program
This paper introduces how to write the first embedded Qt program and implements a demonstration of an electronic clock.
In this article, we continue to practice Qt and implement a stopwatch with the same function as the stopwatch in the mobile phone:
Looking back at the last Qt development process, the entire Qt development is achieved by typing code. In fact, you can also use the UI interface function of Qt Creater to develop a graphical interface through graphical configuration. This article will use this method for development.
1 Create a new Qt project
For the specific steps of creating a Qt project, please refer to the previous article: Embedded Qt - Write and run your first ARM-Qt program . Only the differences are explained here.
The previous article implemented page design through code. This article will use the UI interface design function of Qt Creater, so you need to check the following creation page :
After creation, the Qt default project structure is as follows:
Double-click widget.ui to open the UI settings page, as shown below:
Here is a brief introduction to each functional area:
2. Code Writing
2.1 UI interface design
Change the size of the interface. The resolution of my Linux board screen is 800x480, so adjust it to the corresponding size:
Drag a Label from the left , and then you can modify the font size:
Then drag in other components you need from the left ( PushButton , TextBrower ) and position adjustment components (spring-shaped HorizontalSpacer , VericalSpacer )
To perform horizontal and vertical layout, select the corresponding components, such as the three buttons and the two springs in the middle, and click the horizontal layout button in the upper toolbar:
The horizontal layout of the three buttons is as follows:
Then lay out the other components in turn:
The font can be adjusted to be displayed in the center:
Select the largest component with the mouse, drag the edge to adjust it to the appropriate outer size. Then select components of different levels, adjust the parameters of layoutStretch, and display each component in proportion (equivalent to adjusting the elasticity of each spring component).
Click the triangle icon on the lower left corner, run, and see the effect:
Note that the blank space on the left is for the stopwatch dial.
2.2 Introduction to QTimer and QTime
The QTimer class provides a high-level programming interface for timers, providing both repeating and one-shot timing.
The QTime class provides clock time functionality. A QTime object contains a clock time, which can be expressed as the number of hours, minutes, seconds, and milliseconds since midnight.
Qt Creater provides convenient help documentation. You can directly view the usage of corresponding functions in Qt Creater. For example, search for QTimer to see the corresponding introduction and available API functions:
The functions of QTimer needed in this article are:
-
start: Start the timer
-
stop: Stop the timer
Let's take a look at the introduction of QTime:
The functions of QTime needed in this article are:
-
setHMS: Set the initial time
-
addMSecs: add a time (in milliseconds)
-
toString: Convert time to string format
-
minute: Get the minute
-
second: Get seconds
-
msec: Get milliseconds
2.3 Functions corresponding to buttons
In order to write more understandable code, before writing the code, you need to modify the default name of the corresponding component to a name that is easy to understand. For example, I changed the names of the three buttons to:
-
Btn_Start: Start button with pause/continue function
-
Btn_Reset: Reset button
-
Btn_Hit: Hit button, used to record the time of different rankings
Then you need to manually add QTimer and QTime objects to implement the stopwatch timing function:
2.3.1 Start button processing
The important process in Qt programming is the signal and slot mechanism, which can be implemented manually through the connet function. For the graphical interface design method using Qt Creater, it is usually necessary to continue to connect signals and slots through the interface: right click on the start button and select " Go to slot... ":
Then there are a variety of button signals to choose from. Since the start button also has the function of pause/resume, the toggled function is used here to implement the pause/resume function by using the pressed and released states of the button:
After clicking OK, it will automatically jump to the code page and automatically generate the corresponding slot function framework, and then you can compile the corresponding business logic code in it:
The specific business logic code of the start button is as follows. When it is pressed for the first time, checked is true, and the timer is started to record the timestamp at this time. Then the text of the button is displayed as "Pause", and the reset and dot buttons are grayed out so that these two buttons can no longer be pressed, because it is meaningless to execute reset and dot during pause.
The timer triggers a timeout at regular intervals. Here, ADD_TIME_MSEC is set to 30ms. After the timeout expires, write the corresponding timeout processing function timeout_slot and declare the corresponding signal and slot processing.
void Widget::on_Btn_Start_toggled(bool checked)
{
if (checked)
{
timer.start(ADD_TIME_MSEC);
lastTime = QTime::currentTime(); //Record timestamp
ui->Btn_Start->setText("Pause");
ui->Btn_Reset->setEnabled(false);
ui->Btn_Hit->setEnabled(true);
}
else
{
timer.stop();
ui->Btn_Start->setText("Continue");
ui->Btn_Reset->setEnabled(true);
ui->Btn_Hit->setEnabled(false);
}
}
connect(&timer, SIGNAL(timeout()), this, SLOT(timeout_slot()));
void Widget::timeout_slot()
{
//qDebug("hello");
QTime nowTime = QTime::currentTime();
time = time.addMSecs(lastTime.msecsTo(nowTime));
lastTime = nowTime;
ui->Txt_ShowTime->setText(time.toString("mm:ss.zzz"));
}
After the timeout is reached, the time difference between two times is calculated, and then the time is accumulated through the addMSecs function.
2.3.2 Reset button processing
The reset button is also adjusted to the slot by right clicking. Note that the clicked function can be used here, because the reset button only needs to use its click and press function:
The specific implementation of the corresponding slot function is as follows:
void Widget::on_Btn_Reset_clicked()
{
m_iHitCnt = 0;
timer.stop();
time.setHMS(0,0,0,0);
ui->Txt_ShowTime->setText("00:00:00");
ui->Txt_ShowItem->clear();
ui->Btn_Start->setText("Start");
ui->Btn_Start->setChecked(false);
ui->Btn_Reset->setEnabled(false);
ui->Btn_Hit->setEnabled(false);
}
The main function is to reset the time to zero, display the status, and display status of each button to the default display status.
2.3.3 Processing of the click button
The click button is the same as the reset button, and only the clicked function is used. The specific implementation of the corresponding slot function is as follows:
void Widget::on_Btn_Hit_clicked()
{
QString temp;
m_iHitCnt++;
temp.sprintf("--Count times%d--", m_iHitCnt);
ui->Txt_ShowItem->setFontPointSize(9);
ui->Txt_ShowItem->append(temp);
ui->Txt_ShowItem->setFontPointSize(12);
ui->Txt_ShowItem->append(time.toString("[mm:ss.zzz]"));
}
The dot function is used to record the time of different positions during the operation of the stopwatch and display it in the text display box on the right.
Here, the setFontPointSize function is used to set the font display of different sizes.
2.4 Implementation of the stopwatch dial
In the previous article: Embedded Qt - Write and run your first ARM-Qt program , a clock dial was displayed through code. Based on this article, this article modifies the code to realize a stopwatch dial that displays seconds and minutes. The specific modified code is as follows:
connect(&timer, SIGNAL(timeout()), this, SLOT(update()));
connect(ui->Btn_Reset, SIGNAL(clicked()), this, SLOT(update()));
void Widget::paintEvent(QPaintEvent *event)
{
int side = qMin(width(), height());
//QTime time = QTime::currentTime();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/3, height()*2/5); //Base position of drawing
painter.scale(side/300.0, side/300.0); //Automatically scale with window size
//Dial (3 concentric circles)
for (int i=0; i<PANEL_RADIUS_NUM; i++)
{
QBrush brush(stPanelParaArr .color);
QPen pen(stPanelParaArr .color);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawEllipse(-stPanelParaArr .radius, -stPanelParaArr .radius, 2*stPanelParaArr .radius, 2*stPanelParaArr .radius);
}
// Seconds scale
painter.setPen(secondColor);
for (int i = 0; i < 60; i++)
{
if ((i % 5) == 0)
{
painter.drawLine(PANEL_RADIUS3-8, 0, PANEL_RADIUS3, 0);
QFont font("TimesNewRoman", SEC_NUM_SIZE);
painter.setFont(font);
painter.drawText(-SEC_NUM_SIZE, -(CLOCK_RADIUS-15), 2*SEC_NUM_SIZE, 2*SEC_NUM_SIZE, Qt::AlignHCenter, QString::number(i==0? 60 : i));
}
else
{
painter.drawLine(PANEL_RADIUS3-5, 0, PANEL_RADIUS3, 0);
}
//Seconds are further divided into 5 grids
for (int j = 0; j < 5; j++)
{
painter.rotate(6.0/5);
if (j != 4)
{
painter.drawLine(PANEL_RADIUS3-2, 0, PANEL_RADIUS3, 0);
}
}
}
//Minute scale
painter.setPen(minuteColor);
for (int k = 0; k < 30; k++)
{
if ((k % 5) == 0)
{
painter.rotate(-90.0);
painter.drawLine(PANEL_RADIUS4-8, 0, PANEL_RADIUS4, 0);
painter.rotate(90.0);
QFont font("TimesNewRoman", MIN_NUM_SIZE);
painter.setFont(font);
painter.drawText(-MIN_NUM_SIZE, -(PANEL_RADIUS4-10), 2*MIN_NUM_SIZE, 2*MIN_NUM_SIZE, Qt::AlignHCenter, QString::number(k==0? 30 : k));
}
else
{
painter.rotate(-90.0);
painter.drawLine(PANEL_RADIUS4-4, 0, PANEL_RADIUS4, 0);
painter.rotate(90.0);
}
painter.rotate(12.0);
}
//Minute hand
painter.setPen(Qt::NoPen);
painter.setBrush(minuteColor);
painter.save();
painter.rotate(12.0 * (time.minute() + time.second() / 60.0));
painter.drawConvexPolygon(minuteHand, 3);
painter.restore();
//The second hand
painter.setPen(Qt::NoPen);
painter.setBrush(secondColor);
painter.save();
//painter.rotate(6.0 * time.second());
painter.rotate(6.0 * (time.second()+time.msec()/1000.0));
painter.drawConvexPolygon(secondHand, 3);
painter.restore();
painter.end();
}
The main modification is to remove the previous hour display and replace it with two time rings: an outer second ring and an inner minute ring . The range of the second ring is 0~60 seconds, and the range of the minute ring is 0~30 minutes.
The display effect of the stopwatch dial is as follows:
3 Compile and run
The code is written in Qt Creater in the Window environment, and is first compiled in Windows to view the effect.
3.1 Compiling in Windows
The running effect in Windows is as shown in the right picture below, which can achieve a timing effect similar to the stopwatch in the mobile phone:
3.2 Compiling in Ubuntu
The QT project source code in Windows:
-
.cpp files
-
.h files
-
.pro file
-
.ui File
Copy it to Ubuntu. Note that the .user file is not needed (it is the compilation configuration for the Windows platform).
Then use the compilation tool chain of the ARM platform. Mine is in "/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/". Here you need to use its qmake tool to automatically generate the Makefile file, and then compile it through the make command .
Use qmake to generate Makefile, enter the program source directory, and execute the qmake command:
/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/bin/qmake
After successful execution, you can see the automatically generated Makefile file, and then execute the make command to compile and obtain the executable file.
3.3 Running on Linux board
Put the executable file into the Linux board that has been configured with the Qt runtime environment, run it and view the effect:
Note:
For the specific compilation process in Ubuntu, please refer to the previous article: Embedded Qt - Write and run your first ARM-Qt program
For the configuration of Qt's cross-compilation environment in Ubuntu, please refer to this previous article: Embedded Linux-Qt Environment Construction
4 Conclusion
This article uses a stopwatch example to introduce how to use the UI interface design function of Qt Creator to develop Qt, cross-compile the code, and test the operation in the Linux environment of i.MX6ULL.