반응형
Done
(1) 평소 버튼 hide, 마우스 호버 시에 버튼 show
-> QGridLayout을 삭제하였다. 레이아웃 없이 좌표로 올려놓았다.
-> 배경이 투명으로 되어 있어서 hover event가 오지 않는다.
시간이 업데이트 되는 라벨 위에 마우스가 올라 갈 때만 hover event가 온다. (수정 해야할 사항)
(2) 버튼 스타일 작업
-> 버튼 모서리 둥근 것, normal, hover, pressed일 때 각각 색상을 입혀줬다.
TBD
(1) 디자인 다시 구성
(2) 타이머 라벨 외에 빈 공간(위젯)에 마우스 호버 이벤트 받을 수 있도록 수정
(3) 다른 프로그램 실행 중에도 무조건 항상 상단 유지하도록 변경
(4) 디버깅 방법 추가
(5) 쓰레드 실행 중에 프로그램 종료 버튼 누를 경우, 프로그램 에러 팝업 뜸
-> 쓰레드 종료 전에 main loop가 종료되기 때문에 에러코드를 리턴하며 프로그램이 종료되는 것
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);
setAttribute(Qt::WA_Hover, true);
this->installEventFilter(this);
m_pause = true;
m_mouseMove = true;
m_mouseX = this->geometry().x(); // 현재 마우스 좌표로 초기화
m_mouseY = this->geometry().y();
m_absX = this->geometry().x();
m_absY = this->geometry().y();
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()) );
initUi();
}
/**
*/
void timer::initUi()
{
setFixedSize(480, 150);
ui.label->setText("0 : 0 : 0");
showButtons(false);
QString sheet =
"QPushButton#startButton {"
" color : white;"
" background-color: rgb(58,134,255);"
" border-radius : 6px;"
"}"
"QPushButton#startButton::hover {"
" color : white;"
" background-color: rgb(33,90,181);"
" border-radius : 6px;"
"}"
"QPushButton#startButton::pressed {"
" color : white;"
" background-color: rgb(27,48,82);"
" border-radius : 6px;"
"}"
"QPushButton#pauseButton {"
" color : white;"
" background-color: rgb(58,134,255);"
" border-radius : 6px;"
"}"
"QPushButton#pauseButton::hover {"
" color : white;"
" background-color: rgb(33,90,181);"
" border-radius : 6px;"
"}"
"QPushButton#pauseButton::pressed {"
" color : white;"
" background-color: rgb(27,48,82);"
" border-radius : 6px;"
"}"
"QPushButton#closeButton {"
" color : white;"
" background-color: rgb(58,134,255);"
" border-radius : 6px;"
"}"
"QPushButton#closeButton::hover {"
" color : white;"
" background-color: rgb(33,90,181);"
" border-radius : 6px;"
"}"
"QPushButton#closeButton::pressed {"
" color : white;"
" background-color: rgb(27,48,82);"
" border-radius : 6px;"
"}"
;
setStyleSheet(sheet);
}
/**
*/
void timer::on_closeButton_clicked()
{
// TBD) thead running 중에 quit하면 에러 팝업 나옴
m_clockThread.quit();
QCoreApplication::quit();
}
/**
*/
void timer::on_startButton_clicked()
{
if (m_clockThread.isRunning())
{
m_pause = true;
ui.pauseButton->setText("Pause");
emit resume();
}
else
{
m_clockThread.start();
}
}
/**
*/
void timer::on_pauseButton_clicked()
{
if (m_pause)
{
m_pause = false;
ui.pauseButton->setText("Reset");
emit pause();
}
else
{
m_pause = true;
ui.pauseButton->setText("Pause");
emit reset();
}
}
void timer::showButtons(bool show)
{
if (show)
{
ui.startButton->show();
ui.pauseButton->show();
ui.closeButton->show();
}
else
{
ui.startButton->hide();
ui.pauseButton->hide();
ui.closeButton->hide();
}
}
/**
*/
bool timer::event(QEvent* e)
{
switch (e->type())
{
case QEvent::HoverEnter:
showButtons(true);
return true;
case QEvent::HoverLeave:
showButtons(false);
return true;
default:
break;
}
return QWidget::event(e);
}
/**
*/
void timer::mouseReleaseEvent(QMouseEvent*)
{
m_mouseMove = true;
}
/**
*/
void timer::mouseMoveEvent(QMouseEvent *mouse)
{
if (mouse->button() == Qt::RightButton)
{
return;
}
m_mouseX = QCursor::pos().x();
m_mouseY = QCursor::pos().y();
if (m_mouseMove)
{
m_absX = mouse->pos().x() + 7;
m_absY = mouse->pos().y() + 7;
m_mouseMove = false;
}
this->move(m_mouseX-m_absX, m_mouseY-m_absY);
}
timer.h
#pragma once
#ifndef TIMER_H
#define TIMER_H
#include "clockthread.h"
#include <QWidget>
#include <QMouseEvent>
#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;
bool m_pause;
bool m_mouseMove;
int m_mouseX;
int m_mouseY;
int m_absX;
int m_absY;
private:
void initUi();
void showButtons(bool show);
protected:
virtual bool event(QEvent*);
void mouseReleaseEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
signals:
void resume();
void pause();
void reset();
private slots:
void on_closeButton_clicked();
void on_startButton_clicked();
void on_pauseButton_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>460</width>
<height>130</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>-10</x>
<y>0</y>
<width>480</width>
<height>120</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Arial Rounded MT Bold</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>
<widget class="QPushButton" name="closeButton">
<property name="geometry">
<rect>
<x>380</x>
<y>20</y>
<width>31</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>x</string>
</property>
</widget>
<widget class="QPushButton" name="startButton">
<property name="geometry">
<rect>
<x>140</x>
<y>60</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
<widget class="QPushButton" name="pauseButton">
<property name="geometry">
<rect>
<x>230</x>
<y>60</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>Pause</string>
</property>
</widget>
</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);
}
}
반응형