본문 바로가기
SWE/Qt

Qt 스톱워치 윈도우 프로그램 2day

by S나라라2 2021. 2. 19.
반응형

done

- 메뉴바 없앰 -> QCoreApplication 에서 QWidget으로 변경

- 윈도우에서 프로그램이 최상위 상단에 있도록 -> ok Qt::WindowStayOnTopHint

- pause 동작, pause후에 start재개 -> flag로 count up, start버튼 눌렀을 때 이미 생성된 thread있는지 체크

 

TBD

- 버튼 hide상태이다가 마우스가 위에 올라올 때만 show

- 마우스 클릭에 따라 프로그램 이동

 

main.cpp

timer.cpp timer.h timer.ui

clockthread.cpp clockthread.h

 

main.cpp

#include "timer.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	timer w;
	w.show();
	return a.exec();
}

 

timer.cpp

#include "timer.h"

/**
 */
timer::timer(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	setWindowFlags(Qt::Widget | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
	
	setParent(0); // Create toplevel widget -> ?

	setAttribute(Qt::WA_NoSystemBackground, true);
	// 위젯이 배경이 없는 것을 나타낸다.
	// 위젯이 paint Event를 받을 때, 배경이 자동적으로 다시 그려지지 않는다.
	// WA_OpaquePaintEvent와는 다르게, 새로 노출된 부분이 절대 배경으로 채워지지 않는다.
	// WA_OpaquePaintEvent : 윈도우가 처음에 보여진 이후에, 프로그램이 paint event를 동작시킬 때까지 이것을 통해 user는 볼 수 있다.

	setAttribute(Qt::WA_TranslucentBackground, true);
	// 위젯이 투명한 배경을 가져야만 한다.
	// 위젯의 불투명하지 않은 부분이 투명해진다. 왜냐하면 위젯이 alpha 채널을 가지고 잇기 때문이다.
	// WA_TranslucentBackground 플래그를 셋팅하는 것은 WA_NoSystemBackground를 셋팅하도록 만든다.
	// 또한 윈도우에서 실행되는 프로그램이라면 Qt::FramelessWindowHint 플래그도 설정해야한다.

	setAttribute(Qt::WA_PaintOnScreen); 

	ui.label->setText("0 : 0 : 0");
	setFixedSize(600,240);

	connect(&m_clockThread, SIGNAL(sendTime(QString)), ui.label, SLOT(setText(QString)), Qt::QueuedConnection);
	connect(this, SIGNAL(resume()), &m_clockThread, SLOT(onResume()));
	connect(this, SIGNAL(reset()), &m_clockThread, SLOT(onReset()) );
	connect(this, SIGNAL(pause()), &m_clockThread, SLOT(onPause()) );
}

/**
 */
void timer::on_closeButton_clicked()
{
	//ui.label->setText("clicked closeButton");
	m_clockThread.quit();
	QCoreApplication::quit();
}

/**
 */
void timer::on_startButton_clicked()
{
	//ui.label->setText("clicked startButton");
	if (m_clockThread.isRunning())
	{
		emit resume();
	}
	else
	{
		m_clockThread.start();
	}
}

/**
 */
void timer::on_pauseButton_clicked()
{
	//ui.label->setText("clicked pauseButton");
	//m_clockThread.wait(); // 파라미터 ULONG_MAX 줘야하는건지?

	emit pause();
}

/**
 */
void timer::on_resetButton_clicked()
{
	//ui.label->setText("clicked resetButton");
	emit reset();
}

 

timer.h

#pragma once

#ifndef TIMER_H
#define TIMER_H

#include "clockthread.h"
#include <QtWidgets/QMainWindow>
#include "ui_timer.h"

class ClockThread;

class timer : public QWidget
{
	Q_OBJECT

public:
	timer(QWidget *parent = Q_NULLPTR);

private:
	Ui::timer ui;
	ClockThread m_clockThread;

signals:
	void resume();
	void pause();
	void reset();

private slots:
	void on_closeButton_clicked();
	void on_startButton_clicked();
	void on_pauseButton_clicked();
	void on_resetButton_clicked();
};

#endif

 

timer.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>timer</class>
 <widget class="QWidget" name="timer">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>464</width>
    <height>165</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout_2">
   <property name="leftMargin">
    <number>0</number>
   </property>
   <property name="topMargin">
    <number>0</number>
   </property>
   <property name="rightMargin">
    <number>0</number>
   </property>
   <property name="bottomMargin">
    <number>0</number>
   </property>
   <item row="2" column="0">
    <widget class="QPushButton" name="startButton">
     <property name="text">
      <string>start</string>
     </property>
    </widget>
   </item>
   <item row="2" column="1">
    <widget class="QPushButton" name="pauseButton">
     <property name="text">
      <string>pause</string>
     </property>
    </widget>
   </item>
   <item row="2" column="2">
    <widget class="QPushButton" name="resetButton">
     <property name="text">
      <string>reset</string>
     </property>
    </widget>
   </item>
   <item row="1" column="0" colspan="3">
    <widget class="QLabel" name="label">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="font">
      <font>
       <family>Arial Black</family>
       <pointsize>50</pointsize>
       <weight>75</weight>
       <bold>true</bold>
      </font>
     </property>
     <property name="text">
      <string notr="true">0 : 0 : 0</string>
     </property>
     <property name="alignment">
      <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </item>
   <item row="0" column="2">
    <widget class="QPushButton" name="closeButton">
     <property name="text">
      <string>close</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

 

clockthread.h

#ifndef CLOCKTHREAD_H
#define CLOCKTHREAD_H

#include <QThread>
#include <QObject>

class ClockThread : public QThread
{
	Q_OBJECT;

public:
	ClockThread(QObject* parent=Q_NULLPTR);
	virtual ~ClockThread();

private:
	bool m_firstTime;
	bool m_running;
	int m_hours;
	int m_minutes;
	int m_seconds;

private:
	void init();
	void run();

signals:
	void sendTime(QString time);

private slots:
	void onResume();
	void onPause();
	void onReset();
	void timerHit();
};

#endif

 

clockthread.cpp

#include "clockthread.h"

#include <QTimer>

ClockThread::ClockThread(QObject* parent)
: QThread(parent)
{
	init();
}

ClockThread::~ClockThread()
{
}

void ClockThread::init()
{
	m_running = false;
	m_hours = 0;
	m_minutes = 0;
	m_seconds = 0;

	QString time = QString("%1 : %2 : %3").arg(m_hours).arg(m_minutes).arg(m_seconds);
	emit sendTime(time);
}

void ClockThread::onResume()
{
	m_running = true;
}

void ClockThread::onPause()
{
	m_running = false;
}

void ClockThread::onReset()
{
	init();
	quit();
}

void ClockThread::run()
{
	m_running = true;

	QTimer timer;
	connect(&timer, SIGNAL(timeout()), this, SLOT(timerHit()), Qt::DirectConnection);
	timer.setInterval(1000); // 1000msc = 1 sec
	timer.start();
	exec();
}

void ClockThread::timerHit()
{
	if(m_running)
	{
		m_seconds++;
		if(m_seconds>60)
		{
			m_minutes++;
			m_seconds = 0;
		}
		if(m_minutes>60)
		{
			m_hours++;
			m_minutes = 0;
		}

		QString time = QString("%1 : %2 : %3").arg(m_hours).arg(m_minutes).arg(m_seconds);
		emit sendTime(time);
	}
}
반응형