├── .gitattributes ├── .gitignore ├── LICENSE ├── PictureMatching3 ├── PictureMatching3.pro ├── ThreeDog │ ├── tdabstractbutton.cpp │ ├── tdabstractbutton.h │ ├── tdcheckbox.cpp │ ├── tdcheckbox.h │ ├── tdfadeoutwidget.cpp │ ├── tdfadeoutwidget.h │ ├── tdlistwidget.cpp │ ├── tdlistwidget.h │ ├── tdmenubutton.cpp │ ├── tdmenubutton.h │ ├── tdpushbutton.cpp │ ├── tdpushbutton.h │ ├── tdradiobutton.cpp │ ├── tdradiobutton.h │ ├── tdradiobuttongroup.cpp │ ├── tdradiobuttongroup.h │ ├── tdscrollarea.cpp │ ├── tdscrollarea.h │ ├── tdslider.cpp │ ├── tdslider.h │ ├── tdstackbutton.cpp │ ├── tdstackbutton.h │ ├── tdtoolbar.cpp │ ├── tdtoolbar.h │ ├── tdwidget.cpp │ └── tdwidget.h ├── gamemain.cpp ├── gamemain.h ├── img.qrc ├── img │ ├── 10_hover.png │ ├── 10_normal.png │ ├── 10_selected.png │ ├── 11_hover.png │ ├── 11_normal.png │ ├── 11_selected.png │ ├── 12_hover.png │ ├── 12_normal.png │ ├── 12_selected.png │ ├── 13_hover.png │ ├── 13_normal.png │ ├── 13_selected.png │ ├── 14_hover.png │ ├── 14_normal.png │ ├── 14_selected.png │ ├── 1_hover.png │ ├── 1_normal.png │ ├── 1_selected.png │ ├── 2_hover.png │ ├── 2_normal.png │ ├── 2_selected.png │ ├── 3_hover.png │ ├── 3_normal.png │ ├── 3_selected.png │ ├── 4_hover.png │ ├── 4_normal.png │ ├── 4_selected.png │ ├── 5_hover.png │ ├── 5_normal.png │ ├── 5_selected.png │ ├── 6_hover.png │ ├── 6_normal.png │ ├── 6_selected.png │ ├── 7_hover.png │ ├── 7_normal.png │ ├── 7_selected.png │ ├── 8_hover.png │ ├── 8_normal.png │ ├── 8_selected.png │ ├── 9_hover.png │ ├── 9_normal.png │ ├── 9_selected.png │ ├── begin_hover.png │ ├── begin_normal.png │ ├── begin_press.png │ ├── daohang.png │ ├── defeat.png │ ├── exit_hover.png │ ├── exit_normal.png │ ├── exit_press.png │ ├── game_main.png │ ├── game_main_with_logo.png │ ├── logo.png │ ├── prompt_hover.png │ ├── prompt_normal.png │ ├── prompt_press.png │ ├── reorder_hover.png │ ├── reorder_normal.png │ ├── reorder_press.png │ ├── restart_hover.png │ ├── restart_normal.png │ ├── restart_press.png │ ├── victory.png │ └── welcome.png ├── main.cpp ├── myitem.cpp ├── myitem.h ├── widget.cpp └── widget.h ├── README.md └── show ├── show_1.jpg ├── show_2.jpg ├── show_3.jpg └── show_4.jpg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *,cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # dotenv 80 | .env 81 | 82 | # virtualenv 83 | .venv 84 | venv/ 85 | ENV/ 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | 90 | # Rope project settings 91 | .ropeproject 92 | 93 | # ========================= 94 | # Operating System Files 95 | # ========================= 96 | 97 | # Windows 98 | # ========================= 99 | 100 | # Windows thumbnail cache files 101 | Thumbs.db 102 | ehthumbs.db 103 | ehthumbs_vista.db 104 | 105 | # Folder config file 106 | Desktop.ini 107 | 108 | # Recycle Bin used on file shares 109 | $RECYCLE.BIN/ 110 | 111 | # Windows Installer files 112 | *.cab 113 | *.msi 114 | *.msm 115 | *.msp 116 | 117 | # Windows shortcuts 118 | *.lnk 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2017 ThreeDog 3 | 4 | "THE Sprite-WARE LICENSE" (Revision 1): 5 | ->https://www.github.com/TheThreeDog wrote this file. 6 | As long as you retain this notice you can do whatever you want with this stuff. 7 | If we meet some day, and you think this stuff is worth it, you can buy me a super bottles of Sprite in return. 8 | fork from:https://en.wikipedia.org/wiki/Beerware & https://github.com/bitdust/WamaCry/blob/master/LICENSE.txt 9 | of course, you can copy this and modify it again. 10 | 11 | “雪碧软件协议”(第一版): 12 | ->https://www.github.com/TheThreeDog 编写了此文件。 13 | 只要你还保留本协议文本,你可以以使用此软件做任何事。 14 | 如果我们在某一天相遇了,而且你认为此软件很有价值,你可以为我买一大瓶雪碧来答谢。 15 | 此协议抄袭自:https://en.wikipedia.org/wiki/Beerware 和 https://github.com/bitdust/WamaCry/blob/master/LICENSE.txt 16 | 当然,你可以按照你的喜好来修改此协议. 17 | -------------------------------------------------------------------------------- /PictureMatching3/PictureMatching3.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2017-07-31T09:26:18 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = PictureMatching3 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += main.cpp\ 16 | widget.cpp \ 17 | ThreeDog/tdabstractbutton.cpp \ 18 | ThreeDog/tdcheckbox.cpp \ 19 | ThreeDog/tdfadeoutwidget.cpp \ 20 | ThreeDog/tdlistwidget.cpp \ 21 | ThreeDog/tdmenubutton.cpp \ 22 | ThreeDog/tdpushbutton.cpp \ 23 | ThreeDog/tdradiobutton.cpp \ 24 | ThreeDog/tdradiobuttongroup.cpp \ 25 | ThreeDog/tdscrollarea.cpp \ 26 | ThreeDog/tdslider.cpp \ 27 | ThreeDog/tdstackbutton.cpp \ 28 | ThreeDog/tdtoolbar.cpp \ 29 | ThreeDog/tdwidget.cpp \ 30 | gamemain.cpp \ 31 | myitem.cpp 32 | 33 | HEADERS += widget.h \ 34 | ThreeDog/tdabstractbutton.h \ 35 | ThreeDog/tdcheckbox.h \ 36 | ThreeDog/tdfadeoutwidget.h \ 37 | ThreeDog/tdlistwidget.h \ 38 | ThreeDog/tdmenubutton.h \ 39 | ThreeDog/tdpushbutton.h \ 40 | ThreeDog/tdradiobutton.h \ 41 | ThreeDog/tdradiobuttongroup.h \ 42 | ThreeDog/tdscrollarea.h \ 43 | ThreeDog/tdslider.h \ 44 | ThreeDog/tdstackbutton.h \ 45 | ThreeDog/tdtoolbar.h \ 46 | ThreeDog/tdwidget.h \ 47 | gamemain.h \ 48 | myitem.h 49 | 50 | DISTFILES += \ 51 | img/10_hover.png \ 52 | img/10_normal.png \ 53 | img/10_selected.png \ 54 | img/11_hover.png \ 55 | img/11_normal.png \ 56 | img/11_selected.png \ 57 | img/12_hover.png \ 58 | img/12_normal.png \ 59 | img/12_selected.png \ 60 | img/13_hover.png \ 61 | img/13_normal.png \ 62 | img/13_selected.png \ 63 | img/14_hover.png \ 64 | img/14_normal.png \ 65 | img/14_selected.png \ 66 | img/1_hover.png \ 67 | img/1_normal.png \ 68 | img/1_selected.png \ 69 | img/2_hover.png \ 70 | img/2_normal.png \ 71 | img/2_selected.png \ 72 | img/3_hover.png \ 73 | img/3_normal.png \ 74 | img/3_selected.png \ 75 | img/4_hover.png \ 76 | img/4_normal.png \ 77 | img/4_selected.png \ 78 | img/5_hover.png \ 79 | img/5_normal.png \ 80 | img/5_selected.png \ 81 | img/6_hover.png \ 82 | img/6_normal.png \ 83 | img/6_selected.png \ 84 | img/7_hover.png \ 85 | img/7_normal.png \ 86 | img/7_selected.png \ 87 | img/8_hover.png \ 88 | img/8_normal.png \ 89 | img/8_selected.png \ 90 | img/9_hover.png \ 91 | img/9_normal.png \ 92 | img/9_selected.png \ 93 | img/begin_hover.png \ 94 | img/begin_normal.png \ 95 | img/begin_press.png \ 96 | img/daohang.png \ 97 | img/defeat.png \ 98 | img/exit_hover.png \ 99 | img/exit_normal.png \ 100 | img/exit_press.png \ 101 | img/game_main.png \ 102 | img/game_main_with_logo.png \ 103 | img/logo.png \ 104 | img/prompt_hover.png \ 105 | img/prompt_normal.png \ 106 | img/prompt_press.png \ 107 | img/reorder_hover.png \ 108 | img/reorder_normal.png \ 109 | img/reorder_press.png \ 110 | img/restart_hover.png \ 111 | img/restart_normal.png \ 112 | img/restart_press.png \ 113 | img/victory.png \ 114 | img/welcome.png 115 | 116 | RESOURCES += \ 117 | img.qrc 118 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdabstractbutton.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义抽象按钮类 3 | * File Name: tdabstructbutton.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/12/2 6 | * Description: 自定义抽象按钮类,所有的自定义按钮都继承自这个类,通过 7 | * 函数指针和调用者的指针实现回调函数。也可以用信号和槽。 8 | * 9 | * **************************************************/ 10 | 11 | #include "tdabstractbutton.h" 12 | #include 13 | TDAbstractButton::TDAbstractButton(QWidget *parent) :QLabel (parent) 14 | { 15 | //在构造函数中初始化为NULL,如果没有传参,这两个指针无效,不发生调用 16 | caller = NULL; 17 | func_ptr = NULL; 18 | this->setWordWrap(true);//设置自动换行 19 | move_enable = false; 20 | is_press = false; 21 | this->show(); 22 | } 23 | 24 | void TDAbstractButton::setCallback(QObject *obj, FUNC_PTR func) 25 | { 26 | //设置回调,参数是函数的调用者,和调用的函数指针 27 | caller = obj; 28 | func_ptr = func; 29 | } 30 | 31 | TDAbstractButton::~TDAbstractButton() 32 | { 33 | 34 | } 35 | 36 | void TDAbstractButton::mousePressEvent(QMouseEvent *e) 37 | { 38 | //在可用状态下才触发 39 | if(this->isEnabled()){ 40 | //旧的鼠标相对于本窗体的位置 41 | if(move_enable){ 42 | old_pos = e->pos(); 43 | is_press = true; 44 | } 45 | } 46 | } 47 | 48 | void TDAbstractButton::mouseMoveEvent(QMouseEvent *e) 49 | { 50 | if(is_press && move_enable && this->isEnabled()){ 51 | //窗体之前的位置,加上鼠标相对于本窗体的位置,再减去鼠标按下之前相对于本窗体的位置。 52 | this->move(this->pos() + e->pos() - old_pos); 53 | } 54 | } 55 | 56 | void TDAbstractButton::mouseReleaseEvent(QMouseEvent *e) 57 | { 58 | if(this->isEnabled()){ 59 | //在鼠标抬起事件中实现调用(caller 和 func_ptr不能为空) 60 | if(Qt::LeftButton == e->button() ){ 61 | if(caller && func_ptr) 62 | (caller->*func_ptr)(); 63 | emit clicked(); 64 | if(move_enable){ 65 | is_press = false; 66 | } 67 | } 68 | } 69 | } 70 | 71 | void TDAbstractButton::setAutoMask() 72 | { 73 | } 74 | 75 | void TDAbstractButton::setMoveEnable(const bool can_move) 76 | { 77 | move_enable = can_move; 78 | } 79 | 80 | bool TDAbstractButton::moveEnable() const 81 | { 82 | return move_enable; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdabstractbutton.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义抽象按钮类 3 | * File Name: tdabstructbutton.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/12/2 6 | * Description: 自定义抽象按钮类,所有的自定义按钮都继承自这个类,通过 7 | * 函数指针和调用者的指针实现回调函数。也可以用信号和槽。 8 | * 9 | ****************************************************/ 10 | /**************************************************** 11 | * 修改日志 12 | * 时间:2017/1/6 13 | * 修改内容:增加鼠标按住拖动移动的功能 14 | * 改动者:ThreeDog 15 | * 注意:在实现了mousePressEvent的子类中,此类的此事件不再调用,则 16 | * 无法实现相应功能,方法是在子类此方法中调用父类的此事件函数。 17 | * 包括其他事件也有可能出现此种情况,应注意。 18 | * 19 | * *************************************************/ 20 | 21 | 22 | #ifndef TDABSTRACTBUTTON_H 23 | #define TDABSTRACTBUTTON_H 24 | #include 25 | #include 26 | 27 | //回调函数的函数指针。 28 | typedef void (QObject::*FUNC_PTR )(); 29 | //函数指针的强制类型转换的宏,函数指针不能自动转换,需要自己转换一下。 30 | #define my_selector(_SELECTOR) (FUNC_PTR)(&_SELECTOR) 31 | 32 | class TDAbstractButton : public QLabel 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | explicit TDAbstractButton(QWidget *parent); 38 | //设置回调,参数是函数的调用者,和调用的函数指针 39 | void setCallback(QObject * obj,FUNC_PTR func); 40 | //设置自动遮罩,在子类中自己实现,本类中只有空方法体 41 | virtual void setAutoMask(); 42 | void setMoveEnable(const bool can_move); 43 | bool moveEnable() const; 44 | ~TDAbstractButton(); 45 | protected: 46 | void mousePressEvent(QMouseEvent *e); 47 | void mouseMoveEvent(QMouseEvent *e); 48 | //在鼠标抬起事件中实现调用 49 | void mouseReleaseEvent(QMouseEvent *e); 50 | signals: 51 | void clicked(); 52 | private: 53 | FUNC_PTR func_ptr; 54 | QObject* caller; 55 | 56 | QPoint old_pos; 57 | bool move_enable; 58 | bool is_press; 59 | 60 | }; 61 | 62 | #endif // TDABSTRACTBUTTON_H 63 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdcheckbox.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义复选框按钮类 3 | * File Name: tdcheckbox.h 4 | * Author : ThreeDog 5 | * Date : 2016/12/24 6 | * Description: 自定义复选框类,通过点击事件传递信号,接收信号后通过 7 | * 原来的属性判断,改变属性设置。 8 | * 9 | * **************************************************/ 10 | #include "tdcheckbox.h" 11 | #include 12 | #include 13 | #include 14 | //按默认方式初始化控件 15 | TDCheckbox::TDCheckbox( QWidget *parent,bool *boolean) 16 | :TDAbstractButton(parent) 17 | { 18 | initDefault(boolean); 19 | } 20 | 21 | 22 | TDCheckbox::TDCheckbox(const QString &text,QWidget *parent, bool *boolean) 23 | :TDAbstractButton(parent) 24 | { 25 | initDefault(boolean); 26 | right->setText(text); 27 | } 28 | 29 | TDCheckbox::TDCheckbox(const QString pic_che,const QString pic_non, QWidget *parent, bool *boolean) 30 | :TDAbstractButton(parent) 31 | { 32 | //加载图片设置 33 | pic_checked.load(pic_che); 34 | pic_non_checked.load(pic_non); 35 | //设置为非默认状态 36 | is_default = false; 37 | is_selected = false; 38 | 39 | //在此关联复选框对应的变量,若指针为空,就会用NULL初始化 40 | this->con_bool = boolean; 41 | if(NULL != con_bool) 42 | is_selected = *con_bool; 43 | 44 | //初始化左右控件,设置控件的大小,统统以图片为标准 45 | left = new QLabel(this); 46 | left->setPixmap(pic_checked); 47 | left->setMinimumSize(pic_checked.size()); 48 | left->resize(pic_checked.size()); 49 | right = new QLabel(this); 50 | right->setMinimumSize(80,left->height()); 51 | right->resize(80,left->height()); 52 | this->setMinimumSize(left->width()+right->width(),left->height()); 53 | this->resize(left->width()+right->width(),left->height()); 54 | 55 | if(!is_selected)//按选中状态来选择显示的图片或颜色 56 | left->setPixmap(pic_non_checked); 57 | else 58 | left->setPixmap(pic_checked); 59 | 60 | //设置右控件位置属性和文字 61 | right->setAlignment(Qt::AlignCenter); 62 | right->setText("TDCheckBox");//唯一和普通构造函数有区别的地方 63 | right->move(left->width(),0); 64 | 65 | } 66 | 67 | void TDCheckbox::initDefault(bool * boolean) 68 | { 69 | //如果颜色是无效的,用默认颜色初始化颜色 70 | if(!col_checked.isValid()&&!col_non_checked.isValid()){ 71 | //初始化为默认颜色显示选中和被选中的状态 72 | col_checked = Qt::red; 73 | col_non_checked = Qt::darkRed; 74 | } 75 | //初始化状态为未选中,初始化方式为默认 76 | is_default = true; 77 | is_selected = false; 78 | //在此关联复选框对应的变量,若指针为空,就会用NULL初始化 79 | this->con_bool = boolean; 80 | if(NULL != con_bool) 81 | is_selected = *con_bool; 82 | 83 | this->setMinimumSize(100,20); 84 | this->resize(100,20); 85 | left = new QLabel(this); 86 | left->setAutoFillBackground(true); 87 | right= new QLabel(this); 88 | //设置左侧图标属性和位置 89 | left->resize(20,20); 90 | left->move(0,0); 91 | QPalette palette; 92 | if(!is_selected)//按选中状态来选择显示的图片或颜色 93 | palette.setColor(QPalette::Background,col_non_checked); 94 | else 95 | palette.setColor(QPalette::Background,col_checked); 96 | left->setPalette(palette); 97 | //设置右侧文字的属性和位置 98 | right->setMinimumSize(80,20); 99 | right->resize(80,20); 100 | right->setAlignment(Qt::AlignCenter); 101 | right->setText("TDCheckBox");//唯一和普通构造函数有区别的地方 102 | right->move(20,0); 103 | 104 | } 105 | //设置控件的自动遮罩 106 | void TDCheckbox::setAutoMask() 107 | { //如果pic_checked加载图片,设置他的遮罩为左图片遮罩 108 | if(!pic_checked.isNull()){ 109 | left->setMask(pic_checked.mask()); 110 | this->setMask(left->mask()); 111 | } 112 | } 113 | 114 | void TDCheckbox::connectToBool(bool *boolean) 115 | { 116 | this->con_bool = boolean; 117 | if(NULL != con_bool) 118 | is_selected = *con_bool; 119 | if(is_default){//默认情况下,执行颜色替换 120 | QPalette palette; 121 | if(!is_selected)//按选中状态来选择显示的图片或颜色 122 | palette.setColor(QPalette::Background,col_non_checked); 123 | else 124 | palette.setColor(QPalette::Background,col_checked); 125 | left->setPalette(palette); 126 | }else{//非默认情况下执行图片的替换 127 | if(!is_selected){ 128 | left->setPixmap(pic_non_checked); 129 | } 130 | else{ 131 | left->setPixmap(pic_checked); 132 | } 133 | 134 | } 135 | } 136 | 137 | TDCheckbox::~TDCheckbox() 138 | { 139 | 140 | } 141 | 142 | void TDCheckbox::mousePressEvent(QMouseEvent *e) 143 | { 144 | if(Qt::LeftButton == e->button()){//左键触发 145 | //通过改变状态的接口改变状态,传参为当前选中状态的非值(即现在被选中,则切换成没选中,反之一样) 146 | setChecked(!is_selected); 147 | //在鼠标离开事件里调用父类的鼠标按下事件。 148 | TDAbstractButton::mouseReleaseEvent(e); 149 | } 150 | //2017/1/6 添加 151 | TDAbstractButton::mousePressEvent(e); 152 | } 153 | 154 | void TDCheckbox::mouseReleaseEvent(QMouseEvent *) 155 | { 156 | //无效化复选框类的鼠标离开事件,因为要在鼠标按下事件里触发。 157 | } 158 | 159 | void TDCheckbox::setText(const QString &text) 160 | { 161 | //如果用空文本,则说明不想有右控件,则去除右控件的部分 162 | //并不再执行right.setText(); 163 | if("" == text){ 164 | //把右控件释放掉 165 | delete right; 166 | right = NULL; 167 | this->setMinimumSize(left->size()); 168 | this->resize(left->size()); 169 | //this->setAutoMask(); 170 | return ; 171 | } 172 | if(NULL != right){ 173 | right->setText(text); 174 | } 175 | 176 | } 177 | //返回是否被选中的状态 178 | bool TDCheckbox::isChecked() const 179 | { 180 | return is_selected; 181 | } 182 | //改变选中状态的外部接口 183 | void TDCheckbox::setChecked(bool check) 184 | { 185 | if(is_default){//如果是默认情况,改变左控件颜色 186 | if(!check){//如果传入的是false,则执行这一段代码,设置选中状态为假,并切换颜色 187 | is_selected = false; 188 | if(NULL != con_bool)//只有在不为空时才改变其值 189 | *con_bool = false;//改变关联变量的值为false 190 | QPalette palette; 191 | palette.setColor(QPalette::Background,col_non_checked); 192 | left->setPalette(palette); 193 | }else {//反之亦然 194 | is_selected = true; 195 | if(NULL != con_bool)//只有在不为空时才改变其值 196 | *con_bool = true;//改变关联变量的值为false 197 | QPalette palette; 198 | palette.setColor(QPalette::Background,col_checked); 199 | left->setPalette(palette); 200 | } 201 | }else {//非默认情况,需要执行图片的替换 202 | if(!check){//同样如果传入的是false,则执行这一段代码,设置选中状态为假,并切换图片 203 | is_selected = false; 204 | if(NULL != con_bool)//只有在不为空时才改变其值 205 | *con_bool = false;//改变关联变量的值为false 206 | left->setPixmap(pic_non_checked); 207 | } 208 | else{ 209 | is_selected = true; 210 | if(NULL != con_bool)//只有在不为空时才改变其值 211 | *con_bool = true;//改变关联变量的值为false 212 | left->setPixmap(pic_checked); 213 | } 214 | 215 | } 216 | } 217 | 218 | void TDCheckbox::setColor(const QColor &col_che, const QColor &col_non) 219 | { 220 | //默认方式才有效 221 | if(is_default){ 222 | //用自定义颜色初始化,用用户指定颜色初始化 223 | col_checked = col_che; 224 | col_non_checked = col_non; 225 | 226 | //如果颜色是无效的,用默认颜色初始化颜色 227 | if(!col_checked.isValid()&&!col_non_checked.isValid()){ 228 | //初始化为默认颜色显示选中和被选中的状态 229 | col_checked = Qt::red; 230 | col_non_checked = Qt::darkRed; 231 | } 232 | if(NULL != con_bool) 233 | is_selected = *con_bool; 234 | 235 | QPalette palette; 236 | if(!is_selected)//按选中状态来选择显示的图片或颜色 237 | palette.setColor(QPalette::Background,col_non_checked); 238 | else 239 | palette.setColor(QPalette::Background,col_checked); 240 | left->setPalette(palette); 241 | } 242 | 243 | } 244 | 245 | QLabel *TDCheckbox::getLeftLabel() 246 | { 247 | return this->left; 248 | } 249 | 250 | QLabel *TDCheckbox::getRightLabel() 251 | { 252 | return this->right; 253 | } 254 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdcheckbox.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义复选框按钮类 3 | * File Name: tdcheckbox.h 4 | * Author : ThreeDog 5 | * Date : 2016/12/24 6 | * Description: 自定义复选框类,通过点击事件传递信号,接收信号后通过 7 | * 原来的属性判断,改变属性设置。 8 | * 9 | * **************************************************/ 10 | 11 | #ifndef TDCHECKBOX_H 12 | #define TDCHECKBOX_H 13 | #include "QLabel" 14 | #include "tdabstractbutton.h" 15 | #include 16 | #include 17 | 18 | //继承自抽象按钮类,复用信号和槽和鼠标离开事件代码 19 | class TDCheckbox : public TDAbstractButton 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | explicit TDCheckbox(QWidget *parent = 0,bool* boolean = NULL); 25 | explicit TDCheckbox(const QString &text,QWidget *parent = 0,bool* boolean= NULL); 26 | explicit TDCheckbox(const QString pic_che,const QString pic_non,QWidget *parent = 0,bool* boolean = NULL); 27 | //按图片形式设置自动遮罩 28 | void setAutoMask(); 29 | //关联这个复选框所控制的布尔变量 传递一个bool变量的指针 30 | void connectToBool(bool* boolean); 31 | //重写setText,改变右控件文字 32 | void setText(const QString &); 33 | //返回是否被选中的状态 34 | bool isChecked() const; 35 | //改变选中状态的外部接口 36 | void setChecked(bool check); 37 | //使用设置接口的方式改变颜色,而不是初始化函数 38 | void setColor(const QColor &col_che,const QColor &col_non); 39 | QLabel * getLeftLabel(); 40 | QLabel * getRightLabel(); 41 | 42 | ~TDCheckbox(); 43 | protected: 44 | void mousePressEvent(QMouseEvent *); 45 | void mouseReleaseEvent(QMouseEvent *); 46 | private : 47 | //按默认方式初始化控件 48 | void initDefault(bool* boolean); 49 | 50 | bool is_default; 51 | bool is_selected; 52 | bool *con_bool;//关联的bool变量的指针 53 | QLabel *left; 54 | QLabel *right; 55 | QColor col_checked; 56 | QColor col_non_checked; 57 | QPixmap pic_checked; 58 | QPixmap pic_non_checked; 59 | }; 60 | 61 | #endif // TDCHECKBOX_H 62 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdfadeoutwidget.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdfadeoutwidget.cpp 3 | * Author : ThreeDog 4 | * Date : Thu Jan 05 15:16:32 2017 5 | * Description : 渐隐渐显窗体,利用timer定时器事件设置窗体的透明度来实现 6 | * 淡入淡出的效果,定时器时间可由用户指定。 7 | * 8 | **************************************************************/ 9 | //2017/1/6 10 | //存在问题,只能在单独窗体状态时实现透明渐变,如果是子窗体,则渐变失效 11 | 12 | #include "tdfadeoutwidget.h" 13 | 14 | #include 15 | 16 | TDFadeoutWidget::TDFadeoutWidget(TDWidget *parent) 17 | :TDWidget(parent) 18 | { 19 | init(); 20 | } 21 | 22 | TDFadeoutWidget::TDFadeoutWidget(const QString &img_path, TDWidget *parent) 23 | :TDWidget(img_path,parent) 24 | { 25 | init(); 26 | } 27 | 28 | TDFadeoutWidget::TDFadeoutWidget(const QString &img_path, TDWidget *parent, bool show_window) 29 | :TDWidget(img_path,parent,show_window) 30 | { 31 | init(); 32 | } 33 | 34 | void TDFadeoutWidget::init() 35 | { 36 | timer = new QTimer(this); 37 | is_hide = false; 38 | is_close = true; 39 | this->setWindowOpacity(0.0); //设置初始的透明度为全透明 40 | opacity_inc = 0.01; //透明度增长值 41 | max_opacity = 1.0; //最大透明度 42 | setFadeoutTime(0.2); //通过秒数来设置定时器间隔 43 | is_display = false; //是否显示着 44 | connect(timer,SIGNAL(timeout()),this,SLOT(timeout())); 45 | } 46 | 47 | double TDFadeoutWidget::getFadeoutTime() 48 | { 49 | //获取所用的全部时间 = 透明度从零增长到1增长的次数*每次增长需要的秒数 50 | return (1/opacity_inc)*(timer_interval/1000); 51 | } 52 | 53 | void TDFadeoutWidget::setFadeoutTime(double second) 54 | { 55 | //间隔时间 = 变化的总秒数/(透明度从零增长到1增长的次数) *1000换算成毫秒 56 | timer_interval = second/(1/opacity_inc)*1000; 57 | } 58 | 59 | TDFadeoutWidget::~TDFadeoutWidget() 60 | { 61 | 62 | } 63 | 64 | void TDFadeoutWidget::timeout() 65 | { 66 | //就是在定时器时间里按照设置好的间隔来进行 67 | if(is_display == true){ 68 | if(this->windowOpacity() < 1.0) 69 | this->setWindowOpacity(this->windowOpacity()+opacity_inc); 70 | else 71 | timer->stop(); 72 | }else{ 73 | if(this->windowOpacity() > 0.0) 74 | this->setWindowOpacity(this->windowOpacity()-opacity_inc); 75 | else{ 76 | //这里透明度已经为0了,在这里判断是否需要隐藏或者关闭窗体 77 | if(is_hide) 78 | TDWidget::hide(); 79 | if(is_close) 80 | TDWidget::close(); 81 | timer->stop(); 82 | } 83 | 84 | } 85 | } 86 | 87 | void TDFadeoutWidget::hide() 88 | { 89 | //因为隐藏事件不可用,所以重写只好hide槽函数,跟close原理一样。 90 | is_hide = true; 91 | timer->start(timer_interval); 92 | is_display = false; 93 | } 94 | //在外部调用close函数可以实现效果,主动点击关闭按钮无效 95 | void TDFadeoutWidget::close() 96 | { 97 | is_close = true; 98 | timer->start(timer_interval); 99 | is_display = false; 100 | } 101 | 102 | void TDFadeoutWidget::showEvent(QShowEvent *) 103 | { 104 | timer->start(timer_interval); 105 | is_display = true; 106 | } 107 | 108 | void TDFadeoutWidget::closeEvent(QCloseEvent *e) 109 | { 110 | //在关闭事件的时候无法实现渐隐效果,因为事件和定时器一起被触发 111 | //定时器还没执行完,窗体就关闭了 112 | is_close = true; 113 | timer->start(timer_interval); 114 | is_display = false; 115 | } 116 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdfadeoutwidget.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdfadeoutwidget.h 3 | * Author : ThreeDog 4 | * Date : Thu Jan 05 15:16:32 2017 5 | * Description : 渐隐渐显窗体,利用timer定时器事件设置窗体的透明度来实现 6 | * 淡入淡出的效果,定时器时间可由用户指定。 7 | * 8 | **************************************************************/ 9 | //2017/1/6 10 | //存在问题,只能在单独窗体状态时实现透明渐变,如果是子窗体,则渐变失效 11 | #ifndef _TDFADEOUTWIDGET_H_ 12 | #define _TDFADEOUTWIDGET_H_ 13 | #include "tdwidget.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | class TDFadeoutWidget : public TDWidget 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | explicit TDFadeoutWidget(TDWidget* parent = 0); 25 | explicit TDFadeoutWidget(const QString &img_path,TDWidget *parent = 0); 26 | explicit TDFadeoutWidget(const QString &img_path,TDWidget *parent,bool show_window); 27 | void init(); 28 | double getFadeoutTime(); //获取当前从不透明到全透明所用的时间 29 | void setFadeoutTime(const double second);//设置从不透明到全透明需要用的时间 30 | ~TDFadeoutWidget(); 31 | public slots: 32 | void timeout(); 33 | void hide(); 34 | void close(); 35 | protected: 36 | void showEvent(QShowEvent *); 37 | void closeEvent(QCloseEvent *); 38 | //void hideEvent(QHideEvent *);//在这里写是无效的,因为hide事件在窗体隐藏之后触发 39 | private : 40 | double opacity_inc;//透明度增长值 41 | double max_opacity;//最大透明度 42 | bool is_display; //是否显示着 43 | double timer_interval;//定时器间隔 44 | bool is_hide; //是否隐藏此窗体? 45 | bool is_close; //是否关闭此窗体? 46 | QTimer *timer; 47 | }; 48 | 49 | #endif //TDFADEOUTWIDGET 50 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdlistwidget.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdlistwidget.cpp 3 | * Author : ThreeDog 4 | * Date : Mon Jan 16 17:02:17 2017 5 | * Description : 自定义列表窗体,包含TDListWidget和TDListWidgetItem类 6 | * TDListWidgetItem有默认的初始化方式,子窗体自适应大小,继承自 7 | * TDSCrollArea类。子控件必须继承TDListWidgetItem类。另外子控件 8 | * 必须重新实现setText()函数,如果使用图片,就用空方法体代替。 9 | * 10 | **************************************************************/ 11 | 12 | #include "tdlistwidget.h" 13 | 14 | TDListWidgetItem::TDListWidgetItem(QWidget *parent, Qt::Orientation ot) 15 | :TDMenuButton(parent) 16 | { 17 | init(ot); 18 | } 19 | 20 | TDListWidgetItem::TDListWidgetItem(const QString text, QWidget *parent, Qt::Orientation ot) 21 | :TDMenuButton(text,parent) 22 | { 23 | init(ot); 24 | } 25 | 26 | TDListWidgetItem::TDListWidgetItem(const QString &pic_nor, const QString &pic_hov, const QString &pic_sel, QWidget *parent) 27 | :TDMenuButton(pic_nor,pic_hov,pic_sel,parent) 28 | { 29 | this->show(); 30 | } 31 | 32 | void TDListWidgetItem::setColor(const QColor &col_nor, const QColor &col_hov, const QColor &col_pre) 33 | { 34 | TDMenuButton::setColor(col_nor,col_hov,col_pre); 35 | } 36 | 37 | void TDListWidgetItem::setText(const QString &text) 38 | { 39 | if(this->isDefault()) 40 | TDMenuButton::setText(text); 41 | else 42 | return ; 43 | } 44 | 45 | void TDListWidgetItem::init(Qt::Orientation ot) 46 | { 47 | if(Qt::Horizontal == ot){ 48 | this->setMaximumSize(30,100); 49 | //设置文字纵向显示 50 | this->setWordWrap(true); 51 | this->setAlignment(Qt::AlignTop); 52 | //this->setMinimumHeight(30); 53 | }else if(Qt::Vertical == ot){ 54 | this->resize(100,30); 55 | //this->setMinimumWidth(30); 56 | } 57 | this->setAlignment(Qt::AlignCenter); 58 | 59 | } 60 | 61 | int TDListWidgetItem::getIndex() const 62 | { 63 | return this->index; 64 | } 65 | 66 | void TDListWidgetItem::setIndex(const int i) 67 | { 68 | this->index = i; 69 | } 70 | 71 | TDListWidgetItem::~TDListWidgetItem() 72 | { 73 | 74 | } 75 | 76 | void TDListWidgetItem::mouseDoubleClickEvent(QMouseEvent *) 77 | { 78 | emit doubleClicked(index); 79 | } 80 | 81 | void TDListWidgetItem::mouseReleaseEvent(QMouseEvent *e) 82 | { 83 | emit clicked(index); 84 | TDMenuButton::mouseReleaseEvent(e); 85 | } 86 | 87 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// 88 | 89 | TDListWidget::TDListWidget(QWidget *parent, Qt::Orientation ot) 90 | :TDScrollArea(parent) 91 | { 92 | orientation = ot; 93 | QWidget *w = new QWidget; 94 | w->resize(100,100); 95 | this->setWidget(w); 96 | spacing = 5; 97 | current_index = 0; 98 | } 99 | //添加新条目,设置条目上的文字,以默认的非图片形式添加 100 | void TDListWidget::addItem(const QString &text) 101 | { 102 | //生成条目 103 | TDListWidgetItem *item = new TDListWidgetItem(text,sub_widget,orientation); 104 | if(Qt::Horizontal == orientation){//横向 105 | if( 0 != item_list.count())//将条目移动到相应位置//记得加上spacing 106 | item->move(item_list.last()->x()+item->width()+spacing,item_list.last()->y()); 107 | else{ 108 | item->move(0,0); 109 | } 110 | //重设子窗体的大小 //注意加上spacing 111 | sub_widget->resize((item->width()+spacing)*(item_list.count()+1),item->height()); 112 | this->resize(this->width(),this->height()); 113 | }else if(Qt::Vertical == orientation){ //纵向 114 | if( 0 != item_list.count())//将条目移动到相应位置 115 | item->move(item_list.last()->x(),item_list.last()->y()+item->height()+spacing); 116 | else 117 | item->move(0,0); 118 | sub_widget->resize(item->width(),(item->height()+spacing)*(item_list.count()+1)); 119 | this->resize(this->width(),this->height()); 120 | } 121 | //设置条目的数字标识 122 | item->setIndex(item_list.count()); 123 | if(1 == item->getIndex())//第一个条目,设置为被选中,并且设置当前index为1 124 | this->current_index = 1; 125 | item_list.append(item); 126 | //连接条目的信号和本窗体的槽,监控点击的条目的效果。 127 | connect(item,SIGNAL(clicked(int)),this,SLOT(itemClick(int))); 128 | connect(item,SIGNAL(doubleClicked(int)),this,SLOT(itemDoubleClick(int))); 129 | } 130 | 131 | //添加条目 132 | void TDListWidget::addItem(TDListWidgetItem *item) 133 | { 134 | if(NULL == item) 135 | return ; 136 | item->setParent(sub_widget); 137 | if(Qt::Horizontal == orientation){ 138 | if( 0 != item_list.count()) 139 | item->move(item_list.last()->x()+item->width()+spacing,item_list.last()->y()); 140 | else{ 141 | item->move(0,0); 142 | } 143 | //重设子窗体的大小 144 | sub_widget->resize((item->width()+spacing)*(item_list.count()+1),item->height()); 145 | this->resize(this->width(),this->height()); 146 | }else if(Qt::Vertical == orientation){ 147 | if( 0 != item_list.count()) 148 | item->move(item_list.last()->x(),item_list.last()->y()+item->height()+spacing); 149 | else 150 | item->move(0,0); 151 | //重设子窗体的大小 152 | sub_widget->resize(item->width(),(item->height()+spacing)*(item_list.count()+1)); 153 | this->resize(this->width(),this->height()); 154 | } 155 | //设置条目的数字标识 156 | item->setIndex(item_list.count()); 157 | if(1 == item->getIndex())//第一个条目,设置为被选中,并且设置当前index为1 158 | this->current_index = 1; 159 | item_list.append(item); 160 | //连接条目的信号和本窗体的槽,监控点击的条目的效果。 161 | connect(item,SIGNAL(clicked(int)),this,SLOT(itemClick(int))); 162 | connect(item,SIGNAL(doubleClicked(int)),this,SLOT(itemDoubleClick(int))); 163 | 164 | } 165 | //插入一个文字条目,在index的位置插入。 166 | void TDListWidget::insertItem(int index, const QString &text) 167 | { 168 | if(index >= item_list.count()) 169 | return ; 170 | //生成条目 171 | TDListWidgetItem *item = new TDListWidgetItem(text,this,orientation); 172 | if(Qt::Horizontal == orientation){ 173 | if( 0 != item_list.count()){ 174 | //将标识位置之后的所有条目后移并设置下标+1 175 | for(int i = item_list.count()-1;i >= index-1; i--) 176 | { 177 | TDListWidgetItem *t = item_list.at(i); 178 | t->setIndex(i+1); 179 | t->move(t->x()+t->width()+spacing,t->y()); 180 | } 181 | item->move(item_list.at(index-2)->x()+item->width()+spacing,item_list.last()->y()); 182 | //重设子窗体的大小 183 | sub_widget->resize((item->width()+spacing)*(item_list.count()+1),item->height()); 184 | this->resize(this->width(),this->height()); 185 | } 186 | else{ 187 | item->move(0,0); 188 | } 189 | }else if(Qt::Vertical == orientation){ 190 | if( 0 != item_list.count()){ 191 | //将标识位置之后的所有条目后移并设置下标+1 192 | for(int i = item_list.count()-1;i >= index-1; i--) 193 | { 194 | TDListWidgetItem *t = item_list.at(i); 195 | t->setIndex(i+1); 196 | t->move(t->x(),t->y()+t->height()+spacing); 197 | } 198 | item->move(item_list.last()->x(),item_list.at(index-2)->y()+item->height()+spacing); 199 | //重设子窗体的大小 200 | sub_widget->resize(item->width(),(item->height()+spacing)*(item_list.count()+1)); 201 | this->resize(this->width(),this->height()); 202 | } 203 | else 204 | item->move(0,0); 205 | } 206 | //设置条目的数字标识 207 | item->setIndex(index-1); 208 | item_list.insert(index,item);/////////////////////////////////////////////////////////////////////////////// 209 | //连接条目的信号和本窗体的槽,监控点击的条目的效果。 210 | connect(item,SIGNAL(clicked(int)),this,SLOT(itemClick(int))); 211 | connect(item,SIGNAL(doubleClicked(int)),this,SLOT(itemDoubleClick(int))); 212 | 213 | } 214 | 215 | //在index的位置插入item条目 216 | void TDListWidget::insertItem(int index, TDListWidgetItem *item) 217 | { 218 | if(index >= item_list.count()) 219 | return ; 220 | //生成条目 221 | if(Qt::Horizontal == orientation){ 222 | if( 0 != item_list.count()){ 223 | //将标识位置之后的所有条目后移并设置下标+1 224 | for(int i = item_list.count()-1;i >= index-1; i--) 225 | { 226 | TDListWidgetItem *t = item_list.at(i); 227 | t->setIndex(i+1); 228 | t->move(t->x()+t->width()+spacing,t->y()); 229 | } 230 | item->move(item_list.at(index-2)->x()+item->width()+spacing,item_list.last()->y()); 231 | //重设子窗体的大小 232 | sub_widget->resize((item->width()+spacing)*(item_list.count()+1),item->height()); 233 | this->resize(this->width(),this->height()); 234 | } 235 | else{ 236 | item->move(0,0); 237 | } 238 | }else if(Qt::Vertical == orientation){ 239 | if( 0 != item_list.count()){ 240 | //将标识位置之后的所有条目后移并设置下标+1 241 | for(int i = item_list.count()-1;i >= index-1; i--) 242 | { 243 | TDListWidgetItem *t = item_list.at(i); 244 | t->setIndex(i+1); 245 | t->move(t->x(),t->y()+t->height()+spacing); 246 | } 247 | item->move(item_list.last()->x(),item_list.at(index-2)->y()+item->height()+spacing); 248 | //重设子窗体的大小 249 | sub_widget->resize(item->width(),(item->height()+spacing)*(item_list.count()+1)); 250 | this->resize(this->width(),this->height()); 251 | } 252 | else 253 | item->move(0,0); 254 | } 255 | //设置条目的数字标识 256 | item->setIndex(index-1); 257 | item_list.insert(index,item);/////////////////////////////////////////////////////////////////////////////////// 258 | //连接条目的信号和本窗体的槽,监控点击的条目的效果。 259 | connect(item,SIGNAL(clicked(int)),this,SLOT(itemClick(int))); 260 | connect(item,SIGNAL(doubleClicked(int)),this,SLOT(itemDoubleClick(int))); 261 | 262 | } 263 | 264 | int TDListWidget::getCount() const 265 | { 266 | //获取条目总数 267 | return this->item_list.count(); 268 | } 269 | 270 | //获取当前条目的指针 271 | TDListWidgetItem *TDListWidget::getCurrentItem() 272 | { 273 | if(0 != this->getCurrentIndex()) 274 | return getItem(getCurrentIndex()); 275 | return NULL; 276 | } 277 | 278 | //获取当前条目的下标 279 | int TDListWidget::getCurrentIndex() const 280 | { 281 | for(int i = 0; i < this->getCount();i++){ 282 | if(item_list.at(i)->isSelected()) 283 | return item_list.at(i)->getIndex(); 284 | } 285 | return 0; 286 | } 287 | 288 | //通过指针获取下标 289 | int TDListWidget::getIndex(TDListWidgetItem *item) const 290 | { 291 | for(int i = 0; i < this->getCount();i++){ 292 | if(item_list.at(i) == item) 293 | return item_list.at(i)->getIndex(); 294 | } 295 | return 0; 296 | } 297 | 298 | //通过下标获取下标指针 299 | TDListWidgetItem *TDListWidget::getItem(const int index) 300 | { 301 | if(index >= item_list.count()) 302 | return NULL; 303 | else 304 | return item_list.at(index); 305 | } 306 | 307 | void TDListWidget::setSpacing(const int spac) 308 | { 309 | this->spacing = spac; 310 | } 311 | 312 | int TDListWidget::getSpacing() const 313 | { 314 | return this->spacing; 315 | } 316 | 317 | TDListWidget::~TDListWidget() 318 | { 319 | 320 | } 321 | 322 | void TDListWidget::itemDoubleClick(int index) 323 | { 324 | if(current_index != index){ 325 | emit currentItemChanged(getItem(current_index),getItem(index)); 326 | current_index = index; 327 | emit currentIndexChanged(index); 328 | emit itemChanged(getItem(index)); 329 | } 330 | emit itemDoubleClicked(getItem(index)); 331 | } 332 | 333 | void TDListWidget::itemClick(int index) 334 | { 335 | if(current_index != index){ 336 | emit currentItemChanged(getItem(current_index),getItem(index)); 337 | current_index = index; 338 | emit currentIndexChanged(index); 339 | emit itemChanged(getItem(index)); 340 | } 341 | emit itemClicked(getItem(index)); 342 | 343 | } 344 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdlistwidget.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdlistwidget.h 3 | * Author : ThreeDog 4 | * Date : Mon Jan 16 17:02:17 2017 5 | * Description : 自定义列表窗体,包含TDListWidget和TDListWidgetItem类 6 | * TDListWidgetItem有默认的初始化方式,子窗体自适应大小,继承自 7 | * TDSCrollArea类。子控件必须继承TDListWidgetItem类。另外子控件 8 | * 必须重新实现setText()函数,如果使用图片,就用空方法体代替。 9 | * 10 | **************************************************************/ 11 | #ifndef _TDLISTWIDGET_H_ 12 | #define _TDLISTWIDGET_H_ 13 | #include 14 | #include "tdscrollarea.h" 15 | #include "tdmenubutton.h" 16 | #include 17 | class TDListWidgetItem : public TDMenuButton 18 | { 19 | Q_OBJECT 20 | 21 | public : 22 | explicit TDListWidgetItem(QWidget *parent = 0,Qt::Orientation ot = Qt::Vertical); 23 | explicit TDListWidgetItem(const QString text,QWidget *parent = 0,Qt::Orientation ot = Qt::Vertical); 24 | explicit TDListWidgetItem(const QString &pic_nor,const QString &pic_hov,const QString &pic_sel,QWidget *parent = 0); 25 | void setColor(const QColor &col_nor,const QColor &col_hov,const QColor &col_pre); 26 | //设置文字,所有的子类必须实现(为了配合TDListWidget中的接口) 27 | virtual void setText(const QString &text); 28 | //以默认方式对变量进行初始化 29 | void init(Qt::Orientation ot); 30 | int getIndex() const; 31 | void setIndex(const int i); 32 | ~TDListWidgetItem(); 33 | signals: 34 | void doubleClicked(int index); 35 | void clicked(int index); 36 | protected: 37 | void mouseDoubleClickEvent(QMouseEvent *); 38 | void mouseReleaseEvent(QMouseEvent *); 39 | private : 40 | //每一个条目的唯一标识 41 | int index; 42 | }; 43 | 44 | class TDListWidget : public TDScrollArea 45 | { 46 | Q_OBJECT 47 | 48 | public: 49 | explicit TDListWidget(QWidget *parent = 0,Qt::Orientation ot = Qt::Vertical); 50 | //添加组件 51 | void addItem(const QString &text); 52 | void addItem(TDListWidgetItem *item); 53 | void insertItem(int index,const QString &text); 54 | void insertItem(int index,TDListWidgetItem *item); 55 | //获取总数 56 | int getCount() const; 57 | //获取当前条目或下标 58 | TDListWidgetItem* getCurrentItem(); 59 | int getCurrentIndex() const; 60 | //获取组件||下标 61 | int getIndex(TDListWidgetItem* ) const; 62 | TDListWidgetItem* getItem(const int index); 63 | //删除(2017/2/4尚未实现) 64 | bool removeItem(const int index); 65 | bool removeItem(TDListWidgetItem* item); 66 | //获取、设置 spacing 67 | void setSpacing(const int spac); 68 | int getSpacing () const; 69 | ~TDListWidget(); 70 | signals: 71 | void currentItemChanged(TDListWidgetItem * previous, TDListWidgetItem * current); 72 | void currentIndexChanged(int current); 73 | void itemChanged(TDListWidgetItem * item); 74 | void itemClicked(TDListWidgetItem * item); 75 | void itemDoubleClicked(TDListWidgetItem * item); 76 | private slots: 77 | //私有的槽函数 78 | void itemDoubleClick(int index); 79 | void itemClick(int index); 80 | private: 81 | //垂直or水平 82 | Qt::Orientation orientation; 83 | QVector item_list; 84 | int spacing; 85 | int current_index; 86 | }; 87 | 88 | #endif //TDLISTWIDGET 89 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdmenubutton.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdmenubutton.cpp 3 | * Author : ThreeDog 4 | * Date : Tue Jan 03 11:25:01 2017 5 | * Description : 自定义菜单按钮,相当于菜单,与按钮不同的是点击将其置 6 | * 于被选中的状态,而不是一松开图片就切换回来。 7 | * 8 | **************************************************************/ 9 | 10 | #include "tdmenubutton.h" 11 | 12 | TDMenuButton::TDMenuButton(QWidget *parent) 13 | :TDPushButton("TDMenuButton",parent) 14 | { 15 | //设置此类的焦点触发方式为点击触发 16 | this->setFocusPolicy(Qt::ClickFocus); 17 | is_selected = false; 18 | } 19 | 20 | TDMenuButton::TDMenuButton(const QString &text, QWidget *parent) 21 | :TDPushButton(text,parent) 22 | { 23 | //设置此类的焦点触发方式为点击触发 24 | this->setFocusPolicy(Qt::ClickFocus); 25 | is_selected = false; 26 | } 27 | 28 | TDMenuButton::TDMenuButton(const QString pic_nor, const QString pic_hov, const QString pic_sel, QWidget *parent) 29 | :TDPushButton(pic_nor,pic_hov,pic_sel,parent) 30 | { 31 | //设置此类的焦点触发方式为点击触发 32 | this->setFocusPolicy(Qt::ClickFocus); 33 | is_selected = false; 34 | } 35 | 36 | void TDMenuButton::setColor(const QColor &col_nor, const QColor &col_hov, const QColor &col_sel) 37 | { 38 | TDPushButton::setColor(col_nor,col_hov,col_sel); 39 | } 40 | 41 | bool TDMenuButton::isSelected() const 42 | { 43 | return this->is_selected; 44 | } 45 | 46 | TDMenuButton::~TDMenuButton() 47 | { 48 | 49 | } 50 | 51 | void TDMenuButton::focusInEvent(QFocusEvent *) 52 | { 53 | //获取到焦点,将图片或者颜色替换为选中时的状态 54 | if(is_default){ 55 | QPalette palette; 56 | palette.setColor(QPalette::Background,col_press); 57 | this->setPalette(palette); 58 | }else{ 59 | this->setPixmap(pic_press); 60 | } 61 | } 62 | 63 | void TDMenuButton::focusOutEvent(QFocusEvent *) 64 | { 65 | //失去焦点,将图片或者颜色替换为正常的状态 66 | if(is_default){ 67 | QPalette palette; 68 | palette.setColor(QPalette::Background,col_normal); 69 | this->setPalette(palette); 70 | }else{ 71 | this->setPixmap(pic_normal); 72 | } 73 | is_selected = false; 74 | } 75 | 76 | void TDMenuButton::leaveEvent(QEvent *e) 77 | { 78 | //重写鼠标离开事件,在被选中的状态下不再执行操作 79 | if(is_selected) 80 | e->ignore(); 81 | else 82 | TDPushButton::leaveEvent(e); 83 | } 84 | 85 | void TDMenuButton::enterEvent(QEvent *e) 86 | { 87 | //重写鼠标进入事件,在被选中的状态下不再执行操作 88 | if(is_selected) 89 | e->ignore(); 90 | else 91 | TDPushButton::enterEvent(e); 92 | } 93 | 94 | void TDMenuButton::mousePressEvent(QMouseEvent *e) 95 | { 96 | //保证焦点不变的情况下只触发一次, 97 | if(!is_selected){ 98 | //无效化鼠标按下事件,改为在焦点事件中执行图片替换 99 | //执行“爷爷类”的鼠标离开事件,完成信号的发送和回调函数的调用 100 | TDAbstractButton::mouseReleaseEvent(e); 101 | is_selected = true; 102 | } 103 | //2017/1/6 添加 104 | TDAbstractButton::mousePressEvent(e); 105 | 106 | } 107 | 108 | void TDMenuButton::mouseReleaseEvent(QMouseEvent *) 109 | { 110 | //用空方法体无效化父类的鼠标松开事件 111 | } 112 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdmenubutton.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdmenubutton.h 3 | * Author : ThreeDog 4 | * Date : Tue Jan 03 11:25:01 2017 5 | * Description : 自定义菜单按钮,相当于菜单,与按钮不同的是点击将其置 6 | * 于被选中的状态,而不是一松开图片就切换回来。 7 | * 8 | **************************************************************/ 9 | #ifndef _TDMENUBUTTON_H_ 10 | #define _TDMENUBUTTON_H_ 11 | #include "tdpushbutton.h" 12 | #include 13 | #include 14 | class TDMenuButton :public TDPushButton 15 | { 16 | public: 17 | explicit TDMenuButton(QWidget* parent = 0); 18 | explicit TDMenuButton(const QString &text,QWidget *parent = 0); 19 | explicit TDMenuButton(const QString pic_nor,const QString pic_hov,const QString pic_sel,QWidget *parent = 0); 20 | void setColor(const QColor &col_nor,const QColor &col_hov,const QColor &col_sel); 21 | bool isSelected() const ; 22 | ~TDMenuButton(); 23 | protected: 24 | void focusInEvent(QFocusEvent *); 25 | void focusOutEvent(QFocusEvent *); 26 | void leaveEvent(QEvent *); 27 | void enterEvent(QEvent *); 28 | void mousePressEvent(QMouseEvent *); 29 | void mouseReleaseEvent(QMouseEvent *); 30 | private: 31 | //记录当前的选中状态 32 | bool is_selected; 33 | }; 34 | 35 | #endif //TDMENUBUTTON 36 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdpushbutton.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义按钮类 3 | * File Name: tdpushbutton.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/12/1 6 | * Description: 自定义按钮类,实现按钮的三态和点击效果,没有传图片参数时 7 | * 用默认的背景色和文字,传递参数时,用图片替换三态效果。 8 | * 9 | * **************************************************/ 10 | 11 | #include "tdpushbutton.h" 12 | #include 13 | #include 14 | //默认无参或传递父控件指针的构造函数 15 | TDPushButton::TDPushButton(QWidget *parent) 16 | :TDAbstractButton(parent) 17 | { 18 | this->setAutoFillBackground(true); 19 | this->setMinimumSize(100,30); 20 | QPalette palette; 21 | col_normal = Qt::gray; 22 | col_hover = Qt::lightGray; 23 | col_press = Qt::darkGray; 24 | palette.setColor(QPalette::Background,col_normal); 25 | this->setPalette(palette); 26 | this->setText("TDPushButton"); 27 | this->setAlignment(Qt::AlignCenter); 28 | is_default = true; 29 | } 30 | 31 | void TDPushButton::setColor(const QColor &col_nor, const QColor &col_hov, const QColor &col_pre) 32 | { 33 | //在为默认形式初始化时才可以执行图片替换 34 | if(true == is_default){ 35 | this->setAutoFillBackground(true); 36 | this->setMinimumSize(100,30); 37 | QPalette palette; 38 | col_normal = col_nor; 39 | col_hover = col_hov; 40 | col_press = col_pre; 41 | palette.setColor(QPalette::Background,col_normal); 42 | this->setPalette(palette); 43 | this->setAlignment(Qt::AlignCenter); 44 | } 45 | 46 | } 47 | 48 | //传递文字和父控件参数,构造函数 49 | TDPushButton::TDPushButton(const QString text, QWidget *parent) 50 | :TDAbstractButton(parent) 51 | { 52 | this->setAutoFillBackground(true); 53 | this->setMinimumSize(100,30); 54 | QPalette palette; 55 | col_normal = Qt::gray; 56 | col_hover = Qt::lightGray; 57 | col_press = Qt::darkGray; 58 | palette.setColor(QPalette::Background,col_normal); 59 | this->setPalette(palette); 60 | this->setText(text); 61 | this->setAlignment(Qt::AlignCenter); 62 | is_default = true; 63 | } 64 | 65 | //传递三态图片实现初始化 bool变量为了区别函数重载,无实际意义 66 | TDPushButton::TDPushButton(const QString pic_nor, 67 | const QString pic_hov, 68 | const QString pic_pre, 69 | QWidget *parent):TDAbstractButton(parent) 70 | { 71 | col_normal = Qt::gray; 72 | col_hover = Qt::lightGray; 73 | col_press = Qt::darkGray; 74 | pic_normal.load(pic_nor); 75 | pic_hover.load(pic_hov); 76 | pic_press.load(pic_pre); 77 | this->setMinimumSize(pic_normal.size()); 78 | this->setPixmap(pic_normal); 79 | is_default = false; 80 | } 81 | 82 | //设置自动遮罩,以鼠标经过图片遮罩为按钮的遮罩区域。 83 | void TDPushButton::setAutoMask() 84 | { 85 | if(!pic_normal.isNull()) 86 | this->setMask(pic_hover.mask()); 87 | } 88 | 89 | bool TDPushButton::isDefault() const 90 | { 91 | return this->is_default; 92 | } 93 | TDPushButton::~TDPushButton() 94 | { 95 | 96 | } 97 | 98 | //鼠标经过进入到控件的事件 99 | void TDPushButton::enterEvent(QEvent *) 100 | { 101 | if(is_default){ 102 | QPalette palette; 103 | palette.setColor(QPalette::Background, col_hover); 104 | this->setPalette(palette); 105 | }else { 106 | this->setPixmap(pic_hover); 107 | } 108 | 109 | } 110 | 111 | //鼠标离开控件时触发事件 112 | void TDPushButton::leaveEvent(QEvent *) 113 | { 114 | if(is_default){ 115 | QPalette palette; 116 | palette.setColor(QPalette::Background,col_normal); 117 | this->setPalette(palette); 118 | }else { 119 | this->setPixmap(pic_normal); 120 | } 121 | } 122 | 123 | void TDPushButton::mousePressEvent(QMouseEvent *e) 124 | { 125 | if(is_default && Qt::LeftButton == e->button()){ 126 | QPalette palette; 127 | palette.setColor(QPalette::Background,col_press); 128 | this->setPalette(palette); 129 | }else if(!is_default&& Qt::LeftButton == e->button()){ 130 | this->setPixmap(pic_press); 131 | } 132 | //2017/1/6 添加 133 | TDAbstractButton::mousePressEvent(e); 134 | 135 | } 136 | 137 | void TDPushButton::mouseReleaseEvent(QMouseEvent *e) 138 | { 139 | if(is_default && Qt::LeftButton == e->button()){ 140 | QPalette palette; 141 | palette.setColor(QPalette::Background,col_hover); 142 | this->setPalette(palette); 143 | }else if(!is_default&& Qt::LeftButton == e->button()){ 144 | this->setPixmap(pic_hover); 145 | } 146 | //执行父类的事件,完成按钮点击的效果。 147 | TDAbstractButton::mouseReleaseEvent(e); 148 | } 149 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdpushbutton.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义按钮类 3 | * File Name: tdpushbutton.h 4 | * Author : ThreeDog 5 | * Date : 2016/12/1 6 | * Description: 自定义按钮类,实现按钮的三态和点击效果,没有传图片参数时 7 | * 用默认的背景色和文字,传递参数时,用图片替换三态效果。 8 | * 9 | * **************************************************/ 10 | 11 | #ifndef TDPUSHBUTTON_H 12 | #define TDPUSHBUTTON_H 13 | #include "tdabstractbutton.h" 14 | #include 15 | #include 16 | #include 17 | class TDPushButton : public TDAbstractButton 18 | { 19 | public: 20 | explicit TDPushButton(QWidget *parent = 0); 21 | TDPushButton(const QString text,QWidget *parent = 0); 22 | TDPushButton(const QString pic_nor,const QString pic_hov,const QString pic_pre,QWidget *parent = 0); 23 | //移除QColor初始化接口,改为使用接口设置 24 | void setColor(const QColor & col_nor,const QColor & col_hov,const QColor & col_pre); 25 | virtual void setAutoMask(); 26 | //判断当前控件是否为默认形式初始化(如果为默认,则可以使用setText()等函数,否则调用该函数无效并输出报错信息) 27 | bool isDefault() const; 28 | ~TDPushButton(); 29 | 30 | protected: 31 | void enterEvent(QEvent *); 32 | void leaveEvent(QEvent *); 33 | void mousePressEvent(QMouseEvent *); 34 | void mouseReleaseEvent(QMouseEvent *); 35 | //子类要用到这些变量,所以声明为保护成员 36 | bool is_default; 37 | QPixmap pic_normal; 38 | QPixmap pic_hover; 39 | QPixmap pic_press; 40 | QColor col_normal; 41 | QColor col_hover; 42 | QColor col_press; 43 | 44 | private: 45 | 46 | }; 47 | 48 | #endif // TDPUSHBUTTON_H 49 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdradiobutton.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdradiobutton.cpp 3 | * Author : ThreeDog 4 | * Date : Mon Jan 02 17:22:08 2017 5 | * Description : 自定义单选按钮,继承自自定义复选框类,扩展了单选的功能 6 | * 在被点击时发送radioClicked()信号,由父控件的槽函数实现单选 7 | * 并增加ID属性,用于记录按钮当前的ID。 8 | * 9 | **************************************************************/ 10 | 11 | #include "tdradiobutton.h" 12 | 13 | TDRadioButton::TDRadioButton(QWidget *parent) 14 | :TDCheckbox("TDRadioButton",parent) 15 | { 16 | 17 | } 18 | 19 | TDRadioButton::TDRadioButton(const QString &text, QWidget *parent) 20 | :TDCheckbox(text,parent) 21 | { 22 | 23 | } 24 | 25 | TDRadioButton::TDRadioButton(const QString pic_che, const QString pic_non, QWidget *parent,bool * boolean) 26 | :TDCheckbox(pic_che,pic_non,parent,boolean) 27 | { 28 | this->setText("TDRadioButton"); 29 | 30 | } 31 | 32 | void TDRadioButton::setColor(const QColor col_che, const QColor col_non) 33 | { 34 | TDCheckbox::setColor(col_che,col_non); 35 | } 36 | 37 | void TDRadioButton::setId(const int i) 38 | { 39 | id = i; 40 | } 41 | 42 | 43 | void TDRadioButton::setText(const QString &text) 44 | { 45 | TDCheckbox::setText(text); 46 | } 47 | 48 | int TDRadioButton::getId() const 49 | { 50 | return id; 51 | 52 | } 53 | 54 | TDRadioButton::~TDRadioButton() 55 | { 56 | 57 | } 58 | 59 | void TDRadioButton::mousePressEvent(QMouseEvent *e) 60 | { 61 | //执行父类的按钮按下事件,并且发送单选按钮点击的信号(包含按钮ID参数) 62 | TDCheckbox::mousePressEvent(e); 63 | emit radioClicked(id); 64 | } 65 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdradiobutton.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdradiobutton.h 3 | * Author : ThreeDog 4 | * Date : Mon Jan 02 17:22:08 2017 5 | * Description : 自定义单选按钮,继承自自定义复选框类,扩展了单选的功能 6 | * 在被点击时发送radioClicked()信号,由父控件的槽函数实现单选 7 | * 并增加ID属性,用于记录按钮当前的ID。 8 | * 9 | **************************************************************/ 10 | #ifndef _TDRADIOBUTTON_H_ 11 | #define _TDRADIOBUTTON_H_ 12 | #include"tdcheckbox.h" 13 | 14 | class TDRadioButton : public TDCheckbox 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit TDRadioButton(QWidget *parent = 0); 20 | explicit TDRadioButton(const QString &text,QWidget *parent = 0); 21 | explicit TDRadioButton(const QString pic_che,const QString pic_non,QWidget *parent = 0,bool * boolean = NULL); 22 | void setColor(const QColor col_che,const QColor col_non); 23 | void setId(const int i); 24 | void setText(const QString & text); 25 | int getId() const; 26 | ~TDRadioButton(); 27 | protected: 28 | void mousePressEvent(QMouseEvent *); 29 | signals: 30 | void radioClicked(int id); 31 | private: 32 | int id; 33 | }; 34 | 35 | #endif //TDRADIOBUTTON 36 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdradiobuttongroup.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义单选按钮组类 3 | * File Name: tdradiobuttongroup.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/12/29 6 | * Description: 自定义单选按钮组类,在需要单选按钮的地方创建一个单选按钮组 7 | * 同一个组内,只能有一个按钮被选择。单个的按钮用自定义复选框实现 8 | * 9 | * **************************************************/ 10 | #include "tdradiobuttongroup.h" 11 | #include 12 | #include 13 | //默认情况下的初始化,添加两个复选框按钮,并且保证只能有一个被选中。 14 | TDRadioButtonGroup::TDRadioButtonGroup(TDWidget *parent) : TDWidget(parent) 15 | { 16 | 17 | initDefault(Qt::Horizontal); 18 | } 19 | //指定了方向的初始化 20 | TDRadioButtonGroup::TDRadioButtonGroup(const Qt::Orientation ot, TDWidget *parent) 21 | :TDWidget(parent) 22 | { 23 | initDefault(ot); 24 | } 25 | //指定方向,并在开始就指定了按钮的个数。 26 | TDRadioButtonGroup::TDRadioButtonGroup(const int num, const Qt::Orientation ot, TDWidget *parent) 27 | :TDWidget(parent) 28 | { 29 | initDefault(ot); 30 | if(num > 2) 31 | addButton(num - 2); 32 | } 33 | 34 | TDRadioButtonGroup::TDRadioButtonGroup(const QString pic_che, 35 | const QString pic_non, 36 | TDWidget *parent, 37 | Qt::Orientation ot) 38 | :TDWidget(parent) 39 | { 40 | pic_checked = pic_che; 41 | pic_non_checked = pic_non; 42 | initDefault(ot); 43 | } 44 | 45 | //添加num个按钮 46 | void TDRadioButtonGroup::addButton(const int num) 47 | { 48 | for(int i = 0;i < num; i++ ) 49 | addButton(); 50 | 51 | } 52 | 53 | void TDRadioButtonGroup::addButton(TDRadioButton *btn,int id) 54 | { 55 | radio_buttons.append(btn); 56 | btn->setId(id); 57 | //设置当前按钮被选中,也就是默认情况永远是最后一个按钮被选中 58 | this->buttonClicked(id); 59 | //连接单选按钮被点击的信号和槽 60 | connect(btn,SIGNAL(radioClicked(int)),this,SLOT(buttonClicked(int))); 61 | } 62 | 63 | //单独添加一个按钮 64 | void TDRadioButtonGroup::addButton() 65 | { 66 | //如果图片没有被初始化赋值,就按默认情况初始化 67 | if(pic_checked.isEmpty() && pic_non_checked.isEmpty()) 68 | radio_btn = new TDRadioButton("TDRadioButton",this); 69 | else 70 | radio_btn = new TDRadioButton(pic_checked,pic_non_checked,this); 71 | //分别在容器和布局中添加 72 | radio_buttons.append(radio_btn); 73 | //设置添加的按钮的ID,当前容器的大小,即添加的按钮的ID。 -1即从0开始计算 74 | radio_btn->setId(radio_buttons.count()-1); 75 | main_layout->addWidget(radio_btn); 76 | radio_btn->show(); 77 | //设置当前按钮被选中,也就是默认情况永远是最后一个按钮被选中 78 | this->buttonClicked(radio_buttons.count()-1); 79 | //连接单选按钮被点击的信号和槽 80 | connect(radio_btn,SIGNAL(radioClicked(int)),this,SLOT(buttonClicked(int))); 81 | } 82 | 83 | //删除一个按钮 84 | void TDRadioButtonGroup::removeButton(const int index) 85 | { 86 | //如果下标大于等于按钮的数量,直接返回,内存溢出 87 | if(index >= radio_buttons.count()) 88 | return ; 89 | radio_btn = radio_buttons.at(index); 90 | //删除之前,在其之后的所有按钮的ID都要-1(相当于前移一位) 91 | for(int i = index+1 ; i < radio_buttons.count();i++){ 92 | radio_buttons.at(i)->setId(radio_buttons.at(i)->getId()-1); 93 | }//以此来保证按钮ID的连续一致 94 | main_layout->removeWidget(radio_btn); 95 | radio_buttons.remove(index); 96 | //在布局和容器删除掉之后,销毁掉这个按钮的内存 97 | delete radio_btn; 98 | radio_btn = NULL; 99 | } 100 | //删除掉全部的按钮 101 | void TDRadioButtonGroup::removeAll() 102 | { 103 | for(int i = 0; i < radio_buttons.count(); i++){ 104 | removeButton(i); 105 | } 106 | 107 | } 108 | //返回当前选中的按钮 109 | TDRadioButton* TDRadioButtonGroup::getClickedButton() 110 | { 111 | //遍历所有按钮,如果遇到被选中的就直接返回。 112 | for(int i = 0;i < radio_buttons.count();i++){ 113 | if(radio_buttons.at(i)->isChecked()) 114 | return radio_buttons.at(i); 115 | } 116 | return NULL; 117 | 118 | } 119 | 120 | int TDRadioButtonGroup::getClickedButtonLocation() const 121 | { 122 | //遍历所有按钮,如果遇到被选中的就直接返回。 123 | for(int i = 0;i < radio_buttons.count();i++){ 124 | if(radio_buttons.at(i)->isChecked()) 125 | return i; 126 | } 127 | return 0; 128 | } 129 | 130 | int TDRadioButtonGroup::getClickedButtonId() const 131 | { 132 | //遍历所有按钮,如果遇到被选中的就直接返回。 133 | for(int i = 0;i < radio_buttons.count();i++){ 134 | if(radio_buttons.at(i)->isChecked()) 135 | return radio_buttons.at(i)->getId(); 136 | } 137 | return 0; 138 | } 139 | //移除所有按钮的文字 140 | void TDRadioButtonGroup::removeText() 141 | { 142 | ////////////////////////////////////// 143 | //现存BUG,默认情况下移除文字,重绘遮罩无效。 144 | for(int i = 0;i < radio_buttons.count();i++){ 145 | radio_buttons.at(i)->setText(""); 146 | } 147 | } 148 | //按默认方式初始化 149 | void TDRadioButtonGroup::initDefault(Qt::Orientation ot) 150 | { 151 | this->adjustSize(); 152 | this->setMoveEnable(false); 153 | //判断方向,决定水平还是垂直布局 154 | if(Qt::Vertical == ot) 155 | main_layout = new QVBoxLayout; 156 | else if(Qt::Horizontal == ot) 157 | main_layout = new QHBoxLayout; 158 | //设定完布局方向,添加两个按钮(默认情况) 159 | //addButton(2); 160 | this->setLayout(main_layout); 161 | 162 | } 163 | 164 | QVector *TDRadioButtonGroup::radioButtons() 165 | { 166 | //返回的是指针,所以这里要对容器取地址。 167 | return &radio_buttons; 168 | 169 | } 170 | 171 | TDRadioButtonGroup::~TDRadioButtonGroup() 172 | { 173 | 174 | } 175 | //组中的单选按钮点击的槽函数 176 | void TDRadioButtonGroup::buttonClicked(int id) 177 | { 178 | if(id != this->getClickedButtonId()) 179 | emit radioButtonChanged(id); 180 | //将被点击的按钮设置为真,其余的都设置成假,则达到了单选的效果。 181 | for(int i = 0;i < radio_buttons.count();i++){ 182 | radio_buttons.at(i)->setChecked(false); 183 | if(id == radio_buttons.at(i)->getId()) 184 | radio_buttons.at(i)->setChecked(true); 185 | } 186 | emit radioButtonClicked(id); 187 | //不是第ID个按钮,是ID等于id的按钮 188 | //radio_buttons.at(id)->setChecked(true); 189 | 190 | } 191 | 192 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdradiobuttongroup.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义单选按钮组类 3 | * File Name: tdradiobuttongroup.h 4 | * Author : ThreeDog 5 | * Date : 2016/12/29 6 | * Description: 自定义单选按钮组类,在需要单选按钮的地方创建一个单选按钮组 7 | * 同一个组内,只能有一个按钮被选择。单个的按钮用自定义复选框实现 8 | * 9 | * **************************************************/ 10 | #ifndef TDRADIOBUTTONGROUP_H 11 | #define TDRADIOBUTTONGROUP_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include "tdradiobutton.h" 17 | #include "tdwidget.h" 18 | 19 | class TDRadioButtonGroup : public TDWidget 20 | { 21 | Q_OBJECT 22 | public: 23 | explicit TDRadioButtonGroup(TDWidget *parent = 0); 24 | explicit TDRadioButtonGroup(const Qt::Orientation,TDWidget* parent = 0); 25 | explicit TDRadioButtonGroup(const int num,const Qt::Orientation,TDWidget* parent = 0 ); 26 | //以图片为参数初始化单选按钮组 27 | explicit TDRadioButtonGroup(const QString pic_che 28 | ,const QString pic_non 29 | ,TDWidget *parent = 0 30 | ,Qt::Orientation ot = Qt::Horizontal); 31 | //添加指定数量的按钮 32 | void addButton(const int num); 33 | //添加一个按钮 34 | void addButton(); 35 | //讲一个现有的按钮添加到组中 并指定ID 36 | void addButton(TDRadioButton *btn,int id); 37 | void removeButton(const int index); 38 | void removeAll(); 39 | //返回被选中的按钮的 40 | TDRadioButton* getClickedButton(); 41 | //获取按钮在容器中的位置 42 | int getClickedButtonLocation() const; 43 | //获取选中的按钮的id; 44 | int getClickedButtonId() const ; 45 | //移除所有按钮的文字 46 | void removeText(); 47 | //初始化函数,传递方向参数,决定是水平还是垂直布局 48 | void initDefault(Qt::Orientation ot); 49 | //返回保存按钮的容器的指针 50 | QVector * radioButtons(); 51 | 52 | ~TDRadioButtonGroup(); 53 | //signals:2017/3/7添加,Threedog 54 | signals: 55 | void radioButtonClicked(int id); 56 | void radioButtonChanged(int id); 57 | public slots: 58 | void buttonClicked(int id ); 59 | private : 60 | //用于显示选中和未选中状态的图片 61 | QString pic_checked; 62 | QString pic_non_checked; 63 | 64 | QVector radio_buttons;//用一个按钮容器存放 65 | TDRadioButton * radio_btn;//用于指向当前正在操作的按钮 66 | QBoxLayout *main_layout;//页面的主要布局,根据用户参数决定是水平还是垂直 67 | 68 | }; 69 | 70 | #endif // TDRADIOBUTTONGROUP_H 71 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdscrollarea.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdscrollarea.cpp 3 | * Author : ThreeDog 4 | * Date : Mon Jan 09 15:13:51 2017 5 | * Description : 滚动区域,内部放置一个透明的子窗体,在子窗体中添加控件,如果子窗体 6 | * 大小超过外部窗体,就显示出来滚动条,滚动条大小规格由主窗体占子窗体比例调控 7 | * 8 | **************************************************************/ 9 | 10 | #include "tdscrollarea.h" 11 | #include 12 | #include 13 | #include 14 | TDScrollBar::TDScrollBar(const QColor back_col, const QColor fron_col, TDWidget *parent, Qt::Orientation ot) 15 | :TDWidget(parent) 16 | { 17 | //初始化透明度 18 | opacity_show = 255; 19 | opacity_hide = 180; 20 | 21 | this->setSliderColor(back_col,fron_col); 22 | //以上初始化颜色 、、、、、、、、、、、、、、、、、、、 23 | this->orientation = ot; 24 | is_press = false; 25 | //滑条的宽度 26 | width = 10; 27 | //滑块半径 28 | radius = width/2; 29 | //设置长度 30 | if(Qt::Horizontal == ot){ 31 | this->resize(parent->width(),width); 32 | } 33 | else if(Qt::Vertical == ot){ 34 | this->resize(width,parent->height()); 35 | } 36 | 37 | } 38 | 39 | //获取滑块的位置(左,上) 40 | double TDScrollBar::getPosition() const 41 | { 42 | return this->position; 43 | } 44 | 45 | //获取滑块半径 46 | double TDScrollBar::getRadius() const 47 | { 48 | return this->radius; 49 | } 50 | 51 | //获取滑槽的宽度 52 | double TDScrollBar::getWidth() const 53 | { 54 | return this->width; 55 | } 56 | 57 | int TDScrollBar::getOpacityShow() const 58 | { 59 | return this->opacity_show; 60 | } 61 | 62 | int TDScrollBar::getOpacityHide() const 63 | { 64 | return this->opacity_hide; 65 | } 66 | 67 | TDScrollBar::~TDScrollBar() 68 | { 69 | 70 | } 71 | 72 | void TDScrollBar::mousePressEvent(QMouseEvent *e) 73 | { 74 | //竖直方向 75 | if(Qt::Vertical == orientation){ 76 | if(e->y() - slider_length/2 < 0) 77 | position = 0; 78 | else if(e->y() + slider_length/2 > parentWidget()->height() ){ 79 | position = this->height()-slider_length; 80 | } 81 | else { 82 | position = e->y()-slider_length/2; 83 | } 84 | // //注意这里是负的 85 | // connect_widget->move(connect_widget->x(), 86 | // -connect_widget->height()*position/parentWidget()->height()); 87 | 88 | } 89 | //水平方向 90 | else if(Qt::Horizontal == orientation){ 91 | if(e->x()-slider_length/2 < 0) 92 | position = 0; 93 | else if(e->x() + slider_length/2 > parentWidget()->width()){ 94 | position = parentWidget()->width()-slider_length; 95 | } 96 | else { 97 | position = e->x()-slider_length/2; 98 | } 99 | // //注意这里是负的 100 | // connect_widget->move(-connect_widget->width()*position/parentWidget()->width(), 101 | // connect_widget->y()); 102 | 103 | } 104 | is_press = true; 105 | update(); 106 | } 107 | 108 | void TDScrollBar::mouseMoveEvent(QMouseEvent *e) 109 | { 110 | if(is_press){ 111 | //竖直方向 112 | if(Qt::Vertical == orientation){ 113 | if(e->y()-slider_length/2 < 0) 114 | position = 0; 115 | else if(e->y() + slider_length/2 > parentWidget()->height() ){ 116 | position = this->height()-slider_length+1; 117 | } 118 | else { 119 | position = e->y()-slider_length/2; 120 | } 121 | // //注意这里是负的 122 | // connect_widget->move(connect_widget->x(), 123 | // -connect_widget->height()*position/parentWidget()->height()); 124 | } 125 | //水平方向 126 | else if(Qt::Horizontal == orientation){ 127 | if(e->x()-slider_length/2 < 0) 128 | position = 0; 129 | else if(e->x() + slider_length/2 > parentWidget()->width()){ 130 | position = parentWidget()->width()-slider_length; 131 | } 132 | else { 133 | position = e->x()-slider_length/2; 134 | } 135 | // //注意这里是负的 136 | // connect_widget->move(-connect_widget->width()*position/parentWidget()->width(), 137 | // connect_widget->y()); 138 | 139 | } 140 | update(); 141 | } 142 | } 143 | 144 | void TDScrollBar::mouseReleaseEvent(QMouseEvent *) 145 | { 146 | is_press = false; 147 | 148 | } 149 | 150 | void TDScrollBar::enterEvent(QEvent *) 151 | { 152 | back_on_show = col_back_show; 153 | front_on_show = col_front_show; 154 | update(); 155 | } 156 | 157 | void TDScrollBar::leaveEvent(QEvent *) 158 | { 159 | back_on_show = col_back_hide; 160 | front_on_show = col_front_hide; 161 | update(); 162 | } 163 | 164 | //绘图事件,绘制这个滑动槽 165 | void TDScrollBar::paintEvent(QPaintEvent *) 166 | { 167 | QPainter painter(this); 168 | //注意参数 x,y,width,height 169 | if(Qt::Vertical == orientation){ 170 | //竖直方向 171 | QRect back_rect(0,0,this->width,parentWidget()->height()); 172 | painter.setPen(Qt::NoPen); 173 | painter.setBrush(QBrush(back_on_show)); 174 | painter.drawRoundedRect(back_rect,radius,radius); 175 | QRect slider_rect(0,position,this->width,this->slider_length); 176 | painter.setPen(Qt::NoPen); 177 | painter.setBrush(front_on_show); 178 | painter.drawRoundedRect(slider_rect,radius,radius); 179 | //注意这里是负的 180 | connect_widget->move(connect_widget->x(), 181 | -connect_widget->height()*position/parentWidget()->height()); 182 | 183 | }else if(Qt::Horizontal == orientation){ 184 | QRect back_rect(0,0,parentWidget()->width(),this->width); 185 | painter.setPen(Qt::NoPen); 186 | painter.setBrush(QBrush(back_on_show)); 187 | painter.drawRoundedRect(back_rect,radius,radius); 188 | QRect slider_rect(position,0,this->slider_length,this->width); 189 | painter.setPen(Qt::NoPen); 190 | painter.setBrush(front_on_show); 191 | painter.drawRoundedRect(slider_rect,radius,radius); 192 | //注意这里是负的 193 | connect_widget->move(-connect_widget->width()*position/parentWidget()->width(), 194 | connect_widget->y()); 195 | 196 | } 197 | 198 | } 199 | 200 | //设置位置 201 | void TDScrollBar::setSliderPosition(const double pos) 202 | { 203 | 204 | this->position = pos; 205 | update(); 206 | } 207 | 208 | //设置滑条长度 209 | void TDScrollBar::setSliderLength(const double length) 210 | { 211 | this->slider_length = length; 212 | update(); 213 | } 214 | 215 | //设置半径 216 | void TDScrollBar::setRadius(const double radius) 217 | { 218 | this->radius = radius; 219 | update(); 220 | } 221 | 222 | //设置滑条宽度 223 | void TDScrollBar::setWidth(const double wid) 224 | { 225 | this->width = wid; 226 | this->radius = wid/2; 227 | update(); 228 | } 229 | 230 | //关联一个窗体,控制关联的窗体的移动 231 | void TDScrollBar::connectToWidget(QWidget *w) 232 | { 233 | connect_widget = w; 234 | //设置位置 235 | //纵向 //横向相反 236 | //关联窗体的位置纵坐标(负数)/关联窗体的总高度 * 滑槽总长度 237 | if(Qt::Vertical == orientation){ 238 | double cwy = connect_widget->y(); 239 | double cwh = connect_widget->height(); 240 | double pwh = parentWidget()->height(); 241 | position = cwy/cwh*pwh; 242 | this->resize(width,parentWidget()->height()); 243 | } 244 | else if(Qt::Horizontal == orientation){ 245 | double cwx = connect_widget->x(); 246 | double cww = connect_widget->width(); 247 | double pww = parentWidget()->width(); 248 | position = cwx/cww*pww; 249 | this->resize(parentWidget()->width(),width); 250 | } 251 | //此时位置position如果为负数,则取绝对值即可 252 | //如果是负数,说明窗体在右或下部分,超出了则位置设为0 253 | if(position < 0) 254 | position = -position; 255 | else 256 | position = 0; 257 | //设置滑条长度 258 | if(Qt::Vertical == orientation){ 259 | //主窗体长度 >= 子窗体长度 则不需要滑动条,隐藏此窗体 260 | if(parentWidget()->height() >= connect_widget->height()){ 261 | slider_length = 0; 262 | this->hide(); 263 | }else { 264 | //如果窗体是隐藏的要显示出来 265 | if(this->isHidden()) 266 | this->show(); 267 | //滑块长度 = 主窗体长度/关联窗体长度*滑条长度 268 | //注意这里的计算方式:要用double,不能用int,否则的结果为零 269 | double ph = parentWidget()->height(); 270 | double ch = connect_widget->height(); 271 | slider_length = ph/ch*ph; 272 | } 273 | } 274 | else if(Qt::Horizontal == orientation){ 275 | //主窗体长度 >= 子窗体长度 则不需要滑动条,隐藏此窗体 276 | if(parentWidget()->width() >= connect_widget->width()){ 277 | slider_length = 0; 278 | this->hide(); 279 | }else{ 280 | //如果窗体是隐藏的要显示出来 281 | if(this->isHidden()) 282 | this->show(); 283 | //滑块长度 = 主窗体长度/关联窗体长度*滑条长度 284 | //注意这里的计算方式:要用double,不能用int,否则的结果为零 285 | double pw = parentWidget()->width(); 286 | double cw = connect_widget->width(); 287 | slider_length = pw/cw*pw; 288 | 289 | } 290 | } 291 | } 292 | 293 | void TDScrollBar::setSliderColor(const QColor &col_back, const QColor &col_front) 294 | { 295 | //鼠标在滑槽时显示的颜色 296 | col_back_show = QColor(col_back.red(),col_back.green(),col_back.blue(),opacity_show); 297 | col_front_show = QColor(col_front.red(),col_front.green(),col_front.blue(),opacity_show); 298 | 299 | //如果不在滑槽时,显示减opacity透明度的颜色 300 | int hide_r = col_back_show.red(); 301 | int hide_g = col_back_show.green(); 302 | int hide_b = col_back_show.blue(); 303 | col_back_hide = QColor(hide_r,hide_g,hide_b,opacity_hide); 304 | hide_r = col_front_show.red(); 305 | hide_g = col_front_show.green(); 306 | hide_b = col_front_show.blue(); 307 | col_front_hide = QColor(hide_r,hide_g,hide_b,opacity_hide); 308 | 309 | back_on_show = col_back_hide; 310 | front_on_show = col_front_hide; 311 | 312 | } 313 | 314 | void TDScrollBar::setOpacityShow(const int opacity) 315 | { 316 | this->opacity_show = opacity; 317 | this->setSliderColor(col_back_show,col_front_show); 318 | } 319 | 320 | void TDScrollBar::setOpacityHide(const int opacity) 321 | { 322 | this->opacity_hide = opacity; 323 | this->setSliderColor(col_back_hide,col_front_hide); 324 | } 325 | 326 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`` 327 | 328 | TDScrollArea::TDScrollArea(QWidget *parent) 329 | :TDWidget(parent) 330 | { 331 | sub_widget = NULL; 332 | scroll_h = NULL; 333 | scroll_v = NULL; 334 | this->setMoveEnable(false); 335 | } 336 | 337 | QWidget *TDScrollArea::widget() 338 | { 339 | return sub_widget; 340 | 341 | } 342 | 343 | void TDScrollArea::setWidget(QWidget *w) 344 | { 345 | //如果不为空相当于重设子窗体,需要释放之前的资源 346 | removeWidget(); 347 | 348 | //加入子窗体并重设其父控件 349 | sub_widget = w; 350 | if(sub_widget == NULL) 351 | return ; 352 | sub_widget->setParent(this); 353 | sub_widget->move(0,0); 354 | sub_widget->show(); 355 | 356 | scroll_h = new TDScrollBar(QColor(75,75,75),QColor(200,200,200),this,Qt::Horizontal); 357 | scroll_h->move(0,this->height()-scroll_h->getWidth()); 358 | scroll_h->connectToWidget(sub_widget); 359 | 360 | scroll_v = new TDScrollBar(QColor(75,75,75),QColor(200,200,200),this,Qt::Vertical); 361 | scroll_v->move(this->width()-scroll_v->getWidth(),0); 362 | scroll_v->connectToWidget(sub_widget); 363 | this->wheel_step = 30; 364 | } 365 | 366 | //移除窗体,清理内存 367 | void TDScrollArea::removeWidget() 368 | { 369 | if(sub_widget != NULL){ 370 | sub_widget->close(); 371 | delete sub_widget; 372 | sub_widget = NULL; 373 | 374 | if(NULL != scroll_h ){ 375 | scroll_h->close(); 376 | delete scroll_h; 377 | scroll_h = NULL; 378 | } 379 | if(NULL != scroll_v){ 380 | scroll_v->close(); 381 | delete scroll_v; 382 | scroll_v = NULL; 383 | } 384 | } 385 | } 386 | 387 | int TDScrollArea::wheelStep() const 388 | { 389 | return wheel_step; 390 | } 391 | 392 | void TDScrollArea::setWheelStep(const int step) 393 | { 394 | wheel_step = step; 395 | } 396 | 397 | int TDScrollArea::getVerticalSliderWidth() const 398 | { 399 | return this->scroll_v->getWidth(); 400 | } 401 | 402 | int TDScrollArea::getHorizontalSliderWidth() const 403 | { 404 | return this->scroll_h->getWidth(); 405 | } 406 | 407 | int TDScrollArea::getVerticalSliderRadius() const 408 | { 409 | return this->scroll_v->getRadius(); 410 | } 411 | 412 | int TDScrollArea::getHorizontalSliderRadius() const 413 | { 414 | return this->scroll_h->getRadius(); 415 | } 416 | 417 | TDScrollBar *TDScrollArea::getHorizontalScroll() 418 | { 419 | return this->scroll_h; 420 | } 421 | 422 | TDScrollBar *TDScrollArea::getVerticalScroll() 423 | { 424 | return this->scroll_v; 425 | } 426 | 427 | TDScrollArea::~TDScrollArea() 428 | { 429 | 430 | } 431 | 432 | void TDScrollArea::setSliderWidth(const int width) 433 | { 434 | scroll_v->setWidth((double)width); 435 | scroll_h->setWidth((double)width); 436 | } 437 | 438 | void TDScrollArea::setSliderRadius(const int radius) 439 | { 440 | scroll_v->setRadius((double)radius); 441 | scroll_h->setRadius((double)radius); 442 | } 443 | 444 | void TDScrollArea::setSliderColor(const QColor &col_back, const QColor &col_front) 445 | { 446 | scroll_v->setSliderColor(col_back,col_front); 447 | scroll_h->setSliderColor(col_back,col_front); 448 | } 449 | 450 | void TDScrollArea::setSliderOpacity(const int show_opacity, const int hide_opacity) 451 | { 452 | scroll_v->setOpacityShow(show_opacity); 453 | scroll_v->setOpacityHide(hide_opacity); 454 | scroll_h->setOpacityShow(show_opacity); 455 | scroll_h->setOpacityHide(hide_opacity); 456 | } 457 | 458 | void TDScrollArea::setVerticalSliderWidth(const int width) 459 | { 460 | scroll_v->setWidth((double)width); 461 | } 462 | 463 | void TDScrollArea::setVerticalSliderRadius(const int radius) 464 | { 465 | scroll_v->setRadius((double)radius); 466 | } 467 | 468 | void TDScrollArea::setVerticalSliderColor(const QColor &col_back, const QColor &col_front) 469 | { 470 | scroll_v->setSliderColor(col_back,col_front); 471 | } 472 | 473 | void TDScrollArea::setVerticalSliderOpacity(const int show_opacity, const int hide_opacity) 474 | { 475 | scroll_v->setOpacityShow(show_opacity); 476 | scroll_v->setOpacityHide(hide_opacity); 477 | } 478 | 479 | void TDScrollArea::setHorizontalSliderWidth(const int width) 480 | { 481 | scroll_h->setWidth((double)width); 482 | } 483 | 484 | void TDScrollArea::setHorizontalSliderRadius(const int radius) 485 | { 486 | scroll_h->setRadius((double)radius); 487 | } 488 | 489 | void TDScrollArea::setHorizontalSliderColor(const QColor &col_back, const QColor &col_front) 490 | { 491 | scroll_h->setSliderColor(col_back,col_front); 492 | } 493 | 494 | void TDScrollArea::setHorizontalSliderOpacity(const int show_opacity, const int hide_opacity) 495 | { 496 | scroll_h->setOpacityShow(show_opacity); 497 | scroll_h->setOpacityHide(hide_opacity); 498 | } 499 | 500 | void TDScrollArea::resizeEvent(QResizeEvent *) 501 | { 502 | //子窗体不为空的时候才执行对应代码 503 | if(sub_widget != NULL){ 504 | double w = this->width(); 505 | double sw = sub_widget->width(); 506 | double h = this->height(); 507 | double sh = sub_widget->height(); 508 | 509 | scroll_h->connectToWidget(sub_widget); 510 | scroll_v->connectToWidget(sub_widget); 511 | scroll_h->move(0,this->height()-scroll_h->getWidth()); 512 | scroll_v->move(this->width()-scroll_v->getWidth(),0); 513 | //如果变化过程中,大小超过了子窗体的下或右边界, 514 | //而这时主窗体大小还没有超过子窗体大小,会出现超出子窗体但滑槽还显示 的情况。 515 | //先解决竖直方向,水平方向同理 516 | if(this->height() >= sub_widget->y()+sub_widget->height() 517 | && this->height() < sub_widget->height()){ 518 | 519 | //出现了这种情况就移动子窗体的位置到下边界-子窗体高度。 520 | 521 | //但是因为在子控件的paintEvent()中使用了move,所以现在要移动sub_widget只能使用setSliderPosition(); 522 | //sub_widget->move(sub_widget->x(),this->height()-sub_widget->height()); 523 | scroll_v->setSliderPosition(-(h-sh)/sh*h); 524 | } 525 | if(this->width() >= sub_widget->x()+sub_widget->width() 526 | && this->width() < sub_widget->width()){ 527 | 528 | //出现了这种情况就移动子窗体的位置到右边界-子窗体宽度。 529 | 530 | //但是因为在子控件的paintEvent()中使用了move,所以现在要移动sub_widget只能使用setSliderPosition(); 531 | //sub_widget->move(this->width()-sub_widget->width(),sub_widget->y()); 532 | scroll_h->setSliderPosition(-(w-sw)/sw * w); 533 | } 534 | } 535 | } 536 | 537 | //滚轮事件,这段算法把我折腾死了~ 538 | void TDScrollArea::wheelEvent(QWheelEvent *e) 539 | { 540 | //大前提是子窗体被设置过! 541 | if(sub_widget != NULL) 542 | { 543 | double w = this->width(); 544 | double sw = sub_widget->width(); 545 | double h = this->height(); 546 | double sh = sub_widget->height(); 547 | double temp = wheel_step; 548 | //优先竖直方向的滚轮 549 | if(scroll_v->isVisible()){ 550 | if(e->delta() > 0){//滚动角度大于0,向上滚动 551 | //子窗体向下移动一个步长 552 | //滑块的位置向上移动一小段距离(按比例计算) 553 | if( sub_widget->y() + temp <= 0) 554 | scroll_v->setSliderPosition(scroll_v->getPosition()-temp/sh*h); 555 | else 556 | scroll_v->setSliderPosition(0); 557 | }else{ 558 | if(sub_widget->y()+sub_widget->height() - temp >= this->height()) 559 | scroll_v->setSliderPosition(scroll_v->getPosition()+temp/sh*h); 560 | else 561 | scroll_v->setSliderPosition(-(h-sh)/sh*h+1); 562 | } 563 | }else if(scroll_h->isVisible()){ 564 | if(e->delta() > 0 ){//滚动角度大于0,向左滚动 565 | if(sub_widget->x() + temp <= 0) 566 | scroll_h->setSliderPosition(scroll_h->getPosition()-temp/sw*w); 567 | else 568 | scroll_h->setSliderPosition(0); 569 | }else{ 570 | if( sub_widget->x()+sub_widget->width() - temp >= this->width()) 571 | scroll_h->setSliderPosition(scroll_h->getPosition()+temp/sw*w); 572 | else 573 | scroll_h->setSliderPosition(-(w-sw)/sw * w); 574 | } 575 | }else { 576 | e->ignore(); 577 | } 578 | e->accept(); 579 | 580 | } 581 | } 582 | 583 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdscrollarea.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdscrollarea.h 3 | * Author : ThreeDog 4 | * Date : Mon Jan 09 15:13:51 2017 5 | * Description : 滚动区域,内部放置一个透明的子窗体,在子窗体中添加控件,如果子窗体 6 | * 大小超过外部窗体,就显示出来滚动条,滚动条大小规格由主窗体占子窗体比例调控 7 | * 滚动条的类也封装在这个文件中 8 | * 9 | **************************************************************/ 10 | #ifndef _TDSCROLLAREA_H_ 11 | #define _TDSCROLLAREA_H_ 12 | #include "tdwidget.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | //滚动窗体中的滚动条类 20 | class TDScrollBar : public TDWidget 21 | { 22 | Q_OBJECT 23 | 24 | public : 25 | //初始化接口,背景色,前景色,父控件 26 | explicit TDScrollBar(const QColor back_col ,const QColor fron_col,TDWidget *parent,Qt::Orientation ot = Qt::Vertical); 27 | double getPosition() const ; 28 | double getRadius() const ; 29 | double getWidth() const ; 30 | int getOpacityShow() const; 31 | int getOpacityHide() const; 32 | ~TDScrollBar(); 33 | protected: 34 | void mousePressEvent(QMouseEvent *); 35 | void mouseMoveEvent(QMouseEvent *); 36 | void mouseReleaseEvent(QMouseEvent *); 37 | void enterEvent(QEvent *); 38 | void leaveEvent(QEvent *); 39 | void paintEvent(QPaintEvent *); 40 | public slots: 41 | //设置滑块的位置和长度 42 | void setSliderPosition(const double pos); 43 | void setSliderLength(const double length); 44 | //设置圆角矩形滑块的圆角半径 45 | void setRadius(const double radius); 46 | void setWidth(const double wid); 47 | //关联窗体 48 | void connectToWidget(QWidget *w); 49 | //设置滑块颜色 50 | void setSliderColor(const QColor &col_back,const QColor &col_front); 51 | 52 | void setOpacityShow(const int opacity); 53 | void setOpacityHide(const int opacity); 54 | private : 55 | //滑槽的方向:水平还是竖直 56 | Qt::Orientation orientation; 57 | //鼠标在滑槽是显示的颜色 58 | QColor col_back_show; 59 | QColor col_front_show; 60 | //鼠标离开状态下的颜色 61 | QColor col_back_hide; 62 | QColor col_front_hide; 63 | //正在显示的颜色 64 | QColor back_on_show; 65 | QColor front_on_show; 66 | //鼠标是否按下 67 | bool is_press ; 68 | double length; //滑槽总长度 69 | double slider_length; //滑动条长度 70 | double position; 71 | double radius; 72 | //滑条的宽度 73 | double width; 74 | //滑槽所关联的窗体,滑槽移动,控制哪个窗体移动相应的位置。 75 | 76 | //滑槽的透明度 77 | int opacity_show; 78 | int opacity_hide; 79 | QWidget * connect_widget; 80 | }; 81 | 82 | class TDScrollArea :public TDWidget 83 | { 84 | Q_OBJECT 85 | 86 | public: 87 | 88 | explicit TDScrollArea(QWidget *parent = 0); 89 | QWidget * widget(); 90 | void setWidget(QWidget * w); 91 | void removeWidget(); 92 | //设置和获取滑轮步长 93 | int wheelStep() const; 94 | void setWheelStep(const int step); 95 | 96 | int getVerticalSliderWidth() const ; 97 | int getHorizontalSliderWidth() const; 98 | int getVerticalSliderRadius() const ; 99 | int getHorizontalSliderRadius() const; 100 | TDScrollBar * getHorizontalScroll(); 101 | TDScrollBar * getVerticalScroll(); 102 | 103 | ~TDScrollArea(); 104 | public slots: 105 | void setSliderWidth(const int width); 106 | void setSliderRadius(const int radius); 107 | void setSliderColor(const QColor &col_back,const QColor &col_front); 108 | void setSliderOpacity(const int show_opacity,const int hide_opacity); 109 | void setVerticalSliderWidth(const int width); 110 | void setVerticalSliderRadius(const int radius); 111 | void setVerticalSliderColor(const QColor &col_back,const QColor &col_front); 112 | void setVerticalSliderOpacity(const int show_opacity,const int hide_opacity); 113 | void setHorizontalSliderWidth(const int width); 114 | void setHorizontalSliderRadius(const int radius); 115 | void setHorizontalSliderColor(const QColor &col_back,const QColor &col_front); 116 | void setHorizontalSliderOpacity(const int show_opacity,const int hide_opacity); 117 | 118 | protected: 119 | //大小改变的时候,滚动槽的大小也要改变 120 | void resizeEvent(QResizeEvent *); 121 | void wheelEvent(QWheelEvent *); 122 | //子窗体,子类还要需要继承操作此窗体,所以设为保护。 123 | QWidget * sub_widget; 124 | private: 125 | TDScrollBar * scroll_h; 126 | TDScrollBar * scroll_v; 127 | int wheel_step; 128 | }; 129 | 130 | #endif //TDSCROLLAREA 131 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdslider.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdslider.cpp 3 | * Author : ThreeDog 4 | * Date : Tue Jan 03 15:59:31 2017 5 | * Description : 自定义滑块窗体,参数传递底色,前景色和滑块颜色,采用绘图事件 6 | * 在鼠标松开时触发操作,接口和QSlider尽量保持一致。 7 | * 8 | **************************************************************/ 9 | 10 | #include "tdslider.h" 11 | #include 12 | TDSlider::TDSlider(TDWidget *parent,Qt::Orientation ot) 13 | :TDWidget(parent) 14 | { 15 | col_background = Qt::darkGray; 16 | col_front = Qt::lightGray; 17 | col_button = Qt::white; 18 | orientation = ot; 19 | minimum = 0; 20 | maximum = 100; 21 | slider_position = 0; 22 | slider_radius = 4; 23 | slider_width = 3; 24 | value = 0; 25 | ispress = false; 26 | 27 | } 28 | 29 | TDSlider::TDSlider(const QColor col_bak 30 | , const QColor col_fro 31 | , const QColor col_btn 32 | , TDWidget *parent 33 | , Qt::Orientation ot) 34 | :TDWidget(parent) 35 | { 36 | col_background = col_bak; 37 | col_front = col_fro; 38 | col_button = col_btn; 39 | orientation = ot; 40 | minimum = 0; 41 | maximum = 100; 42 | slider_position = 0; 43 | slider_radius = 4; 44 | slider_width = 3; 45 | value = 0; 46 | ispress = false; 47 | } 48 | 49 | //私有属性的外部接口 50 | 51 | void TDSlider::setMinimum(const int min) 52 | { 53 | minimum = min; 54 | } 55 | 56 | void TDSlider::setMaximum(const int max) 57 | { 58 | maximum = max; 59 | } 60 | 61 | void TDSlider::setRange(const int min, const int max) 62 | { 63 | minimum = min; 64 | maximum = max; 65 | } 66 | 67 | void TDSlider::setOrientation(Qt::Orientation ot) 68 | { 69 | if(ot != orientation){ 70 | orientation = ot; 71 | //更换布局重绘 72 | update(); 73 | } 74 | } 75 | 76 | void TDSlider::setSliderPosition(const int position) 77 | { 78 | //以像素为参数设置位置,注意如果是纵向,slider_position值得是从顶部到滑块的距离 79 | if(Qt::Horizontal == orientation) 80 | slider_position = position; 81 | else if(Qt::Vertical == orientation){ 82 | slider_position = this->height()-position; 83 | } 84 | //重绘 85 | update(); 86 | } 87 | 88 | void TDSlider::setValue(int v) 89 | { 90 | if(v < minimum) 91 | v = minimum; 92 | else if(v > maximum) 93 | v = maximum; 94 | this->value = v; 95 | //按照value的值在本窗体所占的比例改变位置 96 | double val = value; 97 | double min = minimum; 98 | double max = maximum; 99 | //必须要用double,否则会整形除法会得出0 100 | if(Qt::Horizontal == orientation){ 101 | double position = (val - min)/(max-min)*this->width(); 102 | slider_position = position; 103 | }else if(Qt::Vertical == orientation){ 104 | double position = (val - min)/(max-min)*this->height(); 105 | slider_position = this->height()-position; 106 | //垂直方向上用总高度减去position,得到距顶部的高度,才是需要的效果 107 | } 108 | update(); 109 | 110 | } 111 | 112 | void TDSlider::setSliderWidth(const int width) 113 | { 114 | this->slider_width = width; 115 | update(); 116 | } 117 | 118 | void TDSlider::setSliderRadius(const int radius) 119 | { 120 | this->slider_radius = radius; 121 | update(); 122 | } 123 | 124 | void TDSlider::setBackgroundColor(const QColor &color) 125 | { 126 | this->col_background = color; 127 | } 128 | 129 | void TDSlider::setFrontColor(const QColor &color) 130 | { 131 | this->col_front = color; 132 | } 133 | 134 | void TDSlider::setButtonColor(const QColor &color) 135 | { 136 | this->col_button = color; 137 | } 138 | 139 | int TDSlider::getMinimum() const 140 | { 141 | return minimum; 142 | } 143 | 144 | int TDSlider::getMaximum() const 145 | { 146 | return maximum; 147 | } 148 | 149 | int TDSlider::getSliderPosition() const 150 | { 151 | if(Qt::Horizontal == orientation) 152 | return slider_position; 153 | else if(Qt::Vertical == orientation) 154 | return this->height() - slider_position; 155 | //注意如果是纵向的话,获取到的slider_position应该是从底部开始的 156 | return -1; 157 | } 158 | 159 | int TDSlider::getValue() const 160 | { 161 | return this->value; 162 | } 163 | 164 | int TDSlider::getSliderWidth() const 165 | { 166 | return slider_width; 167 | } 168 | 169 | int TDSlider::getSliderRadius() const 170 | { 171 | return slider_radius; 172 | } 173 | 174 | TDSlider::~TDSlider() 175 | { 176 | 177 | } 178 | 179 | void TDSlider::paintEvent(QPaintEvent *) 180 | { 181 | //QRect四个参数 //left top width height!!!! 182 | QPainter p(this); 183 | 184 | //如果方向是水平方向 185 | if(Qt::Horizontal == orientation){ 186 | //先更正滑块位置,如果位置小于半径,则设置为半径,如果位置大于宽度,设置为宽度-半径 187 | if(slider_position < slider_radius/*/2+1*/) 188 | slider_position = slider_radius/*/2+2*/; 189 | if(slider_position > this->width()-slider_radius*5/4) 190 | slider_position = this->width()-slider_radius*5/4; 191 | 192 | QRect rect(0,slider_radius,this->width(),slider_width); 193 | //先绘制一个与窗体等长的背景色矩形 194 | p.fillRect(rect,col_background); 195 | QRect rect2(0,slider_radius,slider_position,slider_width); 196 | //然后绘制一个从0到当前滑块位置的前景色矩形 197 | p.fillRect(rect2,col_front); 198 | //圆心坐标 199 | QPoint center(slider_position,slider_radius+slider_width/2); 200 | p.setBrush(col_button); 201 | p.setPen(col_button); 202 | //在的滑块的位置画一个半径为4的小圆,作为滑块 203 | p.drawEllipse(center,slider_radius,slider_radius); 204 | }//如果方向是垂直方向 205 | else if(Qt::Vertical == orientation){ 206 | //先更正滑块位置,如果位置大于高度,则设置为高度-5,如果位置小于3,设置为4 207 | if(slider_positionthis->height()-slider_radius*5/4) 210 | slider_position = this->height()-slider_radius*5/4; 211 | //注意此时的sliderposition位置是从上到下的距离 212 | 213 | QRect rect(slider_radius,0,slider_width,this->height()); 214 | //注意竖着的矩形是从上往下画的,所以跟刚才反过来 215 | //先用前景色画一个等高的矩形 216 | p.fillRect(rect,col_front); 217 | QRect rect2(slider_radius,0,slider_width,slider_position); 218 | //再用背景色画一个从最高点到指定位置的矩形 219 | p.fillRect(rect2,col_background); 220 | if(slider_position < slider_radius) 221 | slider_position = slider_radius; 222 | QPoint center(slider_radius+slider_width/2,slider_position); 223 | p.setBrush(col_button); 224 | p.setPen(col_button); 225 | //在滑块的位置画一个小圆作为滑块 226 | p.drawEllipse(center,slider_radius,slider_radius); 227 | } 228 | 229 | } 230 | 231 | void TDSlider::mousePressEvent(QMouseEvent *e) 232 | { 233 | if(Qt::Horizontal == orientation){ 234 | //如果要是落在了范围之外,要把位置校准回来 235 | if(e->x()>slider_radius && e->x()width()-slider_radius*5/4) 236 | this->slider_position = e->pos().x(); 237 | else if(e->x() <= slider_radius) 238 | this->slider_position = slider_radius; 239 | else if(e->x() >= this->width()-slider_radius*5/4) 240 | this->slider_position = this->width()-slider_radius*5/4; 241 | 242 | update(); 243 | ispress = true; 244 | }else if(Qt::Vertical == orientation){ 245 | if(e->y() > slider_radius && e->y()height()-slider_radius*5/4){ 246 | this->slider_position = e->pos().y(); 247 | }else if(e->y() < slider_radius){ 248 | this->slider_position = slider_radius; 249 | }else if(e->y() > this->height()-slider_radius*5/4){ 250 | this->slider_position = this->height()-slider_radius*5/4; 251 | } 252 | update(); 253 | ispress = true; 254 | } 255 | } 256 | 257 | void TDSlider::mouseReleaseEvent(QMouseEvent *e) 258 | { 259 | if(Qt::Horizontal == orientation){ 260 | if(e->x() > slider_radius && e->y()width()-slider_radius*5/4) 261 | slider_position = e->pos().x(); 262 | //如果超出边界y就不再等于e.y() 263 | double x = e->pos().x(); 264 | if(e->x() < 0) 265 | x = 0; 266 | if(e->x() > this->width()) 267 | x = this->width(); 268 | double w = this->width(); 269 | //发送数值改变信号,通过相对位置计算得到数值大小 270 | double value = x/w*(maximum-minimum)+minimum; 271 | emit valueChanged(value); 272 | emit positionChanged(x); 273 | }else if(Qt::Vertical == orientation){ 274 | if(e->y()>slider_radius && e->y()height()-slider_radius*5/4) 275 | slider_position = e->pos().y(); 276 | //如果超出边界y就不再等于e.y() 277 | double y = e->y(); 278 | if(e->y()< 0) 279 | y = 0; 280 | else if(e->y()>this->height()) 281 | y = this->height(); 282 | double w = this->height(); 283 | //发送数值改变信号,通过相对位置计算得到数值大小 284 | //而垂直方向的是从顶部到滑槽点的距离,所以value要减一下 285 | double value = maximum - y/w*(maximum-minimum); 286 | //注意锁定范围 287 | emit valueChanged(value); 288 | emit positionChanged(this->height()-y);//同样这里要用高度减一下 289 | } 290 | update(); 291 | ispress = false; 292 | 293 | } 294 | 295 | void TDSlider::mouseMoveEvent(QMouseEvent *e) 296 | { 297 | if(Qt::Horizontal == orientation){ 298 | if(e->x()>slider_radius && e->x()width()-slider_radius*5/4){ 299 | this->slider_position = e->pos().x(); 300 | }else if(e->x() <= slider_radius){ 301 | this->slider_position = slider_radius; 302 | }else if(e->x() >= this->width()-slider_radius*5/4){ 303 | this->slider_position = this->width()-slider_radius*5/4; 304 | } 305 | //以上校准滑块位置 306 | //以下校准发送的数据 307 | double x = e->pos().x(); 308 | if(x < 0) 309 | x = 0; 310 | if(x > this->width()) 311 | x = this->width(); 312 | double w = this->width(); 313 | double value = x/w*(maximum-minimum)+minimum; 314 | emit valueChanging(value); 315 | emit positionChanging(x); 316 | }else if(Qt::Vertical == orientation){ 317 | if(e->y()> slider_radius &&e->y()height()-slider_radius*5/4){ 318 | this->slider_position = e->pos().y(); 319 | }else if(e->y() < slider_radius){ 320 | this->slider_position = slider_radius; 321 | }else if(e->y() > this->height()-slider_radius*5/4){ 322 | this->slider_position = this->height()-slider_radius*5/4; 323 | } 324 | //以上校准滑块位置 325 | //以下校准发送的数据 326 | double y = e->y(); 327 | if(e->y()< 0) 328 | y = 0; 329 | else if(e->y()>this->height()) 330 | y = this->height(); 331 | 332 | double w = this->height(); 333 | 334 | //发送数值改变信号,通过相对位置计算得到数值大小 335 | //而垂直方向的是从顶部到滑槽点的距离,所以value要减一下 336 | double value = maximum - y/w*(maximum-minimum); 337 | emit valueChanging(value); 338 | emit positionChanging(this->height() - y);//同样这里要用高度减一下 339 | } 340 | update(); 341 | } 342 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdslider.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdslider.h 3 | * Author : ThreeDog 4 | * Date : Tue Jan 03 15:59:31 2017 5 | * Description : 自定义滑块窗体,参数传递底色,前景色和滑块颜色,采用绘图事件 6 | * 在鼠标松开时触发操作,接口和QSlider尽量保持一致。 7 | * 8 | **************************************************************/ 9 | #ifndef _TDSLIDER_H_ 10 | #define _TDSLIDER_H_ 11 | #include "tdwidget.h" 12 | #include 13 | #include 14 | #include 15 | 16 | class TDSlider :public TDWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | 22 | explicit TDSlider(TDWidget *parent = 0,Qt::Orientation ot = Qt::Horizontal); 23 | explicit TDSlider(const QColor col_bak 24 | ,const QColor col_fro 25 | ,const QColor col_btn 26 | ,TDWidget *parent = 0 27 | ,Qt::Orientation ot = Qt::Horizontal); 28 | //所有属性的外部接口 29 | int getMinimum() const; 30 | int getMaximum() const; 31 | int getSliderPosition() const ; 32 | int getValue() const; 33 | int getSliderWidth() const ; 34 | int getSliderRadius() const ; 35 | 36 | ~TDSlider(); 37 | public slots: 38 | //外部接口设置为槽函数,可以供接收槽函数使用 39 | void setMinimum(const int min); 40 | void setMaximum(const int max); 41 | void setRange(const int min,const int max); 42 | void setOrientation(Qt::Orientation ot); 43 | void setSliderPosition(const int position); 44 | void setValue(int v); 45 | void setSliderWidth(const int width); 46 | void setSliderRadius(const int radius); 47 | //设置滑动条的颜色 48 | void setBackgroundColor(const QColor &color); 49 | void setFrontColor(const QColor &color); 50 | void setButtonColor(const QColor &color); 51 | protected: 52 | void paintEvent(QPaintEvent *); 53 | void mousePressEvent(QMouseEvent *); 54 | void mouseReleaseEvent(QMouseEvent *); 55 | void mouseMoveEvent(QMouseEvent *); 56 | signals: 57 | //发送数值改变信号和位置改变信号 58 | void valueChanged(double); 59 | void positionChanged(double); 60 | void valueChanging(double); 61 | void positionChanging(double); 62 | private: 63 | QColor col_background; 64 | QColor col_front; 65 | QColor col_button; 66 | //滑块范围的最小值 67 | int minimum; 68 | //滑块范围的最大值 69 | int maximum; 70 | //滑块窗体的方向 71 | Qt::Orientation orientation; 72 | //滑块的位置 73 | int slider_position; 74 | //滑块当前位置所指定的值 75 | int value; 76 | //记录鼠标是否按下的状态 77 | bool ispress; 78 | //滑动条宽度 79 | int slider_width; 80 | //滑块半径 81 | int slider_radius; 82 | 83 | }; 84 | 85 | #endif //TDSLIDER 86 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdstackbutton.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdstackbutton.cpp 3 | * Author : ThreeDog 4 | * Date : Thu Jan 05 10:19:40 2017 5 | * Description : 自定义堆叠按钮,利用一个内置的StackWidget实现,效果是点击 6 | * 一个按钮触发效果后切换为另一个按钮。例如音乐播放器中播放模式的按钮 7 | * 8 | **************************************************************/ 9 | 10 | #include "tdstackbutton.h" 11 | #include 12 | TDStackButton::TDStackButton(TDWidget *parent) 13 | :TDWidget(parent) 14 | { 15 | stack_layout = new QStackedLayout; 16 | this->setLayout(stack_layout); 17 | 18 | } 19 | 20 | //添加按钮 21 | void TDStackButton::addButton(TDAbstractButton *button) 22 | { 23 | stack_layout->addWidget(button); 24 | stack_layout->setCurrentWidget(button); 25 | connect(button,SIGNAL(clicked()),this,SLOT(toNextButton())); 26 | } 27 | 28 | //移除按钮 29 | void TDStackButton::removeButton(QWidget *button) 30 | { 31 | emit buttonRemoved(stack_layout->indexOf(button)); 32 | stack_layout->removeWidget(button); 33 | //发送移除信号并移除此按钮 34 | } 35 | 36 | //按下标移除按钮 37 | void TDStackButton::removeButton(const int index) 38 | { 39 | if(index >= stack_layout->count()) 40 | return ; 41 | emit buttonRemoved(index); 42 | stack_layout->removeWidget((QWidget * )stack_layout->itemAt(index)); 43 | } 44 | 45 | //移除所有按钮 46 | void TDStackButton::removeAllButton() 47 | { 48 | for(int i = 0; i< stack_layout->count();i++){ 49 | removeButton(i); 50 | } 51 | } 52 | 53 | //获取当前下标 54 | int TDStackButton::getCurrentIndex() const 55 | { 56 | return stack_layout->currentIndex(); 57 | } 58 | 59 | //获取当前的按钮 60 | TDAbstractButton *TDStackButton::getCurrentButton() const 61 | { 62 | return (TDAbstractButton*)stack_layout->currentWidget(); 63 | } 64 | 65 | TDStackButton::~TDStackButton() 66 | { 67 | 68 | } 69 | 70 | //设置按下标当前按钮 71 | void TDStackButton::setCurrentIndex(const int index) 72 | { 73 | if(index >= stack_layout->count()) 74 | return ; 75 | if(index != stack_layout->currentIndex()){ 76 | emit buttonChanged(index); 77 | stack_layout->setCurrentIndex(index); 78 | } 79 | } 80 | 81 | //设置当前按钮 82 | void TDStackButton::setCurrentButton(TDAbstractButton *button) 83 | { 84 | if(button != stack_layout->currentWidget()){ 85 | emit buttonChanged(stack_layout->indexOf(button)); 86 | stack_layout->setCurrentWidget(button); 87 | } 88 | } 89 | 90 | //切换到下一个按钮 91 | void TDStackButton::toNextButton() 92 | { 93 | if(stack_layout->currentIndex()+1 == stack_layout->count()) 94 | stack_layout->setCurrentIndex(0); 95 | else 96 | stack_layout->setCurrentIndex(stack_layout->currentIndex()+1); 97 | } 98 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdstackbutton.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * File Name : tdstackbutton.h 3 | * Author : ThreeDog 4 | * Date : Thu Jan 05 10:19:40 2017 5 | * Description : 自定义堆叠按钮,利用一个内置的StackWidget实现,效果是点击 6 | * 一个按钮触发效果后切换为另一个按钮。例如音乐播放器中播放模式的按钮 7 | * 8 | **************************************************************/ 9 | #ifndef _TDSTACKBUTTON_H_ 10 | #define _TDSTACKBUTTON_H_ 11 | #include "tdwidget.h" 12 | #include "tdabstractbutton.h" 13 | #include 14 | class TDStackButton : public TDWidget 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit TDStackButton(TDWidget *parent = 0); 20 | //添加一个按钮 21 | void addButton(TDAbstractButton * button); 22 | //移除按钮 23 | void removeButton(QWidget * button); 24 | void removeButton(const int index); 25 | void removeAllButton(); 26 | //获取当前按钮或下标 27 | int getCurrentIndex() const ; 28 | TDAbstractButton * getCurrentButton() const ; 29 | ~TDStackButton(); 30 | signals: 31 | void buttonChanged(int index); 32 | void buttonRemoved(int index); 33 | public slots: 34 | //设置当前按钮 35 | void setCurrentIndex(const int index); 36 | void setCurrentButton(TDAbstractButton *button); 37 | //切换至下一个按钮 38 | void toNextButton(); 39 | 40 | private: 41 | QStackedLayout * stack_layout; 42 | 43 | }; 44 | 45 | #endif //TDSTACKBUTTON 46 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdtoolbar.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义工具栏按钮类 3 | * File Name: tdtoolbar.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/12/28 6 | * Description: 自定义工具栏类,继承自自定义复选框,几乎没有改动,只是 7 | * 去除了复选框的右控件,可以通过信号和槽或者回调函数实现功能。 8 | * 9 | * **************************************************/ 10 | #include "tdtoolbar.h" 11 | #include 12 | TDToolbar::TDToolbar(QWidget *parent) 13 | :TDCheckbox(parent,NULL) 14 | { 15 | this->setText(""); 16 | } 17 | 18 | TDToolbar::TDToolbar(const QString pic_che,const QString pic_non, QWidget *parent) 19 | :TDCheckbox(pic_che,pic_non,parent,NULL) 20 | { 21 | this->setText(""); 22 | } 23 | 24 | void TDToolbar::resize(int w, int h) 25 | { 26 | this->getLeftLabel()->resize(w,h); 27 | } 28 | 29 | void TDToolbar::setColor(const QColor &col_che, const QColor &col_non) 30 | { 31 | TDCheckbox::setColor(col_che,col_non); 32 | } 33 | 34 | TDToolbar::~TDToolbar() 35 | { 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdtoolbar.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义工具栏按钮类 3 | * File Name: tdtoolbar.h 4 | * Author : ThreeDog 5 | * Date : 2016/12/28 6 | * Description: 自定义工具栏类,继承自自定义复选框,几乎没有改动,只是 7 | * 去除了复选框的右控件,可以通过信号和槽或者回调函数实现功能。 8 | * 9 | * **************************************************/ 10 | #ifndef TDTOOLBAR_H 11 | #define TDTOOLBAR_H 12 | #include "tdcheckbox.h" 13 | 14 | class TDToolbar : public TDCheckbox 15 | { 16 | public: 17 | explicit TDToolbar(QWidget *parent); 18 | explicit TDToolbar(const QString pic_che,const QString pic_non,QWidget *parent = 0); 19 | void resize(int w,int h); 20 | void setColor(const QColor &col_che,const QColor &col_non); 21 | ~TDToolbar(); 22 | }; 23 | 24 | #endif // TDTOOLBAR_H 25 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdwidget.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义窗体类 3 | * File Name: tdwidget.cpp 4 | * Author : ThreeDog 5 | * Date : 2016/11/30 6 | * Description: 自定义窗体类,实现用图片代替不规则窗体,可拖动。 7 | * 8 | * **************************************************/ 9 | #include "tdwidget.h" 10 | #include 11 | #include 12 | #include 13 | TDWidget::TDWidget(QWidget *parent) : QWidget(parent) 14 | { 15 | //一定初始化为false,否则默认会赋值true,mouseMoveEvent会在点击别的控件时触发! 16 | this->is_press = false; 17 | move_enable = false; 18 | } 19 | 20 | TDWidget::TDWidget(QString img_path,QWidget *parent,bool show_window) : QWidget(parent) 21 | { 22 | //如果不显示窗体,默认情况 23 | if(!show_window){ 24 | this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowMinimizeButtonHint); 25 | this->setAttribute(Qt::WA_TranslucentBackground); 26 | bg_pic.load(img_path); 27 | this->resize(bg_pic.size()); 28 | //this->setMask(bg_pic.mask()); 29 | //一定听初始化为false,否则默认会赋值true,mouseMoveEvent会在点击别的控件时触发! 30 | this->is_press = false; 31 | move_enable = true; 32 | }else{ 33 | //2017,1,9日修改 34 | //显示窗体,传入参数作为背景图片 35 | this->setAutoFillBackground(true); //Widget增加背景图片时,这句一定要。 36 | QPixmap pixmap(img_path); 37 | QPalette palette; 38 | palette.setBrush(QPalette::Background, QBrush(pixmap)); 39 | this->setPalette(palette); 40 | this->is_press = false; 41 | move_enable = false; 42 | } 43 | this->show(); 44 | } 45 | 46 | void TDWidget::setMoveEnable(const bool can_move) 47 | { 48 | this->move_enable = can_move; 49 | } 50 | 51 | bool TDWidget::moveEnable() const 52 | { 53 | return this->move_enable; 54 | } 55 | 56 | void TDWidget::setAutoMask() 57 | { 58 | if(!bg_pic.isNull()) 59 | this->setMask(bg_pic.mask()); 60 | } 61 | 62 | void TDWidget::paintEvent(QPaintEvent *) 63 | { 64 | if(!bg_pic.isNull()){ 65 | QPainter p(this); 66 | p.drawPixmap(0,0,bg_pic); 67 | } 68 | } 69 | 70 | TDWidget::~TDWidget() 71 | { 72 | 73 | } 74 | 75 | void TDWidget::mousePressEvent(QMouseEvent *e) 76 | { 77 | if(Qt::LeftButton == e->button()&&move_enable){ 78 | //旧的鼠标相对于本窗体的位置 79 | old_pos = e->pos(); 80 | is_press = true; 81 | } 82 | } 83 | 84 | void TDWidget::mouseMoveEvent(QMouseEvent *e) 85 | { 86 | if(is_press && move_enable){ 87 | //窗体之前的位置,加上鼠标相对于本窗体的位置,再减去鼠标按下之前相对于本窗体的位置。 88 | this->move(this->pos() + e->pos() - old_pos); 89 | } 90 | } 91 | 92 | void TDWidget::mouseReleaseEvent(QMouseEvent *) 93 | { 94 | if(move_enable) 95 | is_press = false; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /PictureMatching3/ThreeDog/tdwidget.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Program Assigment : 自定义窗体类 3 | * File Name: tdwidget.h 4 | * Author : ThreeDog 5 | * Date : 2016/11/30 6 | * Description: 自定义窗体类,实现用图片代替不规则窗体,可拖动。 7 | * 8 | * **************************************************/ 9 | #ifndef TDWIDGET_H 10 | #define TDWIDGET_H 11 | #include 12 | #include 13 | #include 14 | #include 15 | class TDWidget : public QWidget 16 | { 17 | Q_OBJECT 18 | public: 19 | explicit TDWidget(QWidget *parent = 0); 20 | //2017、1、9 修改构造函数,增加一个bool变量,是否显示边框,默认不显示 21 | TDWidget(QString img_path,QWidget *parent = 0,bool show_window = false); 22 | void setMoveEnable(const bool can_move); 23 | bool moveEnable() const; 24 | void setAutoMask(); 25 | 26 | ~TDWidget(); 27 | protected: 28 | void mousePressEvent(QMouseEvent *); 29 | void mouseMoveEvent(QMouseEvent *); 30 | void mouseReleaseEvent(QMouseEvent *); 31 | void paintEvent(QPaintEvent *); 32 | 33 | private : 34 | bool is_press; 35 | bool move_enable; 36 | QPoint old_pos; 37 | QPixmap bg_pic; 38 | }; 39 | 40 | #endif // TDWIDGET_H 41 | -------------------------------------------------------------------------------- /PictureMatching3/gamemain.cpp: -------------------------------------------------------------------------------- 1 | #include "gamemain.h" 2 | #include 3 | #include 4 | 5 | #include 6 | using namespace std; 7 | 8 | GameMain::GameMain(QWidget *parent) 9 | :TDWidget(":/img/game_main_with_logo.png",parent) 10 | { 11 | //生成四个导航栏按钮 12 | TDPushButton * guideBtn1 = new TDPushButton(":/img/restart_normal.png",":/img/restart_hover.png",":/img/restart_press.png",this); 13 | guideBtn1->move(140,41); 14 | //重新开始 15 | guideBtn1->setCallback(this,my_selector(GameMain::restart)); 16 | TDPushButton * guideBtn2 = new TDPushButton(":/img/reorder_normal.png",":/img/reorder_hover.png",":/img/reorder_press.png",this); 17 | guideBtn2->move(250,41); 18 | //重新排序 19 | guideBtn2->setCallback(this,my_selector(GameMain::reorder)); 20 | TDPushButton * guideBtn3 = new TDPushButton(":/img/prompt_normal.png",":/img/prompt_hover.png",":/img/prompt_press.png",this); 21 | guideBtn3->move(360,41); 22 | //提示 23 | guideBtn3->setCallback(this,my_selector(GameMain::prompt)); 24 | TDPushButton * guideBtn4 = new TDPushButton(":/img/exit_normal.png",":/img/exit_hover.png",":/img/exit_press.png",this); 25 | guideBtn4->move(470,41); 26 | //结束游戏 27 | guideBtn4->setCallback(this,my_selector(GameMain::exitGame)); 28 | 29 | //初始化指针数组中所有都只想空 30 | for(int i = 0 ; i< 11 ; i++) 31 | for(int j = 0; j < 6 ; j++) 32 | items[i][j] = NULL; 33 | //初始化当前下标为0,代表没有选中的图片 34 | currentIndex = 0; 35 | //初始化当前选中的方块为空、代表没有选中 36 | curItem = NULL; 37 | //调用creatItems生成方块 38 | this->createItems(); 39 | //游戏开始启动定时器 40 | timerId = this->startTimer(10000); 41 | 42 | } 43 | //生成方块 44 | void GameMain::createItems() 45 | { 46 | srand(time(NULL)); 47 | int randIndex; 48 | //生成所有的方块。 49 | //给数组中一个个赋值。 50 | QString str1,str2,str3; 51 | for(int i = 0; i < 11 ; i++) 52 | { 53 | for(int j = 0; j < 6; j++) 54 | { 55 | if(items[i][j] == NULL){ 56 | //通过随机数指定按哪个图片进行生成 57 | randIndex = rand()%14+1; 58 | str1 =":/img/"+ QString("%1").arg(randIndex)+"_normal.png"; 59 | str2 =":/img/"+ QString("%1").arg(randIndex)+"_hover.png"; 60 | str3 =":/img/"+ QString("%1").arg(randIndex)+"_selected.png"; 61 | 62 | items[i][j] = new MyItem(str1,str2,str3,this); 63 | items[i][j]->move(100+i*65,100+j*65); 64 | //每一个方块通过下标计算位置并移动 65 | items[i][j]->setIndex(randIndex); 66 | 67 | //绑定方块被点击的信号和本地槽函数 68 | connect(items[i][j],SIGNAL(clicked(MyItem*,int)),this,SLOT(itemClicked(MyItem*,int))); 69 | //每生成一个方块,就生成另一个对应的方块,保证每个方块都是偶数个 70 | creatAnotherItem(randIndex); 71 | } 72 | } 73 | } 74 | //方块的图片是随机的。 75 | } 76 | //判断可以连通的函数 77 | bool GameMain::canConnect(MyItem *item1, MyItem *item2) 78 | { 79 | //先校验指针不为空 80 | if(item1 == NULL || item2 == NULL) 81 | return false; 82 | //提取两个方块数组中所处的位置 83 | int x1 = (item1->x()-100)/65; 84 | int y1 = (item1->y()-100)/65; 85 | int x2 = (item2->x()-100)/65; 86 | int y2 = (item2->y()-100)/65; 87 | // bool ret = false; 88 | // ret = canConnect(x1,x2,y2,y2); 89 | // return ret; 90 | return canConnect(x1,y1,x2,y2); 91 | 92 | } 93 | //重载一个连通函数接口 94 | bool GameMain::canConnect(int x1, int y1, int x2, int y2) 95 | { 96 | //先判断横向可连通 97 | if(horizontalCheck(x1,y1,x2,y2)) 98 | return true; 99 | //在判断纵向可连通 100 | if(verticalCheck(x1,y1,x2,y2)) 101 | return true; 102 | //判断一个拐点的可连通情况 103 | if(turnOnceCheck(x1,y1,x2,y2)) 104 | return true; 105 | //判断两个拐点的可连通情况 106 | if(turnTwiceCheck(x1,y1,x2,y2)) 107 | return true; 108 | //都不可连通,返回false 109 | return false; 110 | } 111 | 112 | bool GameMain::horizontalCheck(int x1, int y1, int x2, int y2) 113 | { 114 | //横向 115 | //判断两次点击的不是同一个方块 116 | if(x1 == x2 && y1 == y2) 117 | return false; 118 | //判断个的纵坐标相同 119 | if(y1 != y2) 120 | return false; 121 | int startX = min(x1,x2); 122 | int endX = max(x1,x2); 123 | //判断两个方块是否相邻 124 | if((endX - startX) == 1) 125 | return true; 126 | //判断两个方块通路上是否都是NULL,有一个不是,就说明不能联通,返回false 127 | for(int i = startX+1; i < endX; i++){ 128 | if(items[i][y1] != NULL) 129 | return false; 130 | } 131 | return true; 132 | } 133 | 134 | bool GameMain::verticalCheck(int x1, int y1, int x2, int y2) 135 | { 136 | //纵向校验 137 | //判断两次点击不是同一个方块 138 | if(x1 == x2 && y1 == y2) 139 | return false; 140 | //判断两个横坐标相同 141 | if(x1 != x2) 142 | return false; 143 | int startY = min(y1,y2); 144 | int endY = max(y1,y2); 145 | //判断两个方块是否相邻 146 | if((endY - startY) == 1) 147 | return true; 148 | //判断两方块儿通路上是否可连。 149 | for(int i = startY+1;i < endY; i++){ 150 | if(items[x1][i] != NULL) 151 | return false; 152 | } 153 | return true; 154 | 155 | } 156 | 157 | bool GameMain::turnOnceCheck(int x1, int y1, int x2, int y2) 158 | { 159 | //实现单拐点校验。 160 | if(x1 == x2 && y1 == y2) 161 | return false; 162 | //一个拐点,说明两个方块必须在不同行不同列! 163 | if(x1 != x2 && y1 != y2){ 164 | //cx cy dx dy 记录两个拐点的坐标 165 | int cx = x1; 166 | int cy = y2; 167 | int dx = x2; 168 | int dy = y1; 169 | //拐点为空,从第一个点到拐点并且从拐点到第二个点可通,则整条路可通。 170 | if(items[cx][cy] == NULL){ 171 | if(verticalCheck(x1,y1,cx,cy) && horizontalCheck(cx,cy,x2,y2)) 172 | return true; 173 | } 174 | if(items[dx][dy] == NULL){ 175 | if(horizontalCheck(x1,y1,dx,dy) && verticalCheck(dx,dy,x2,y2)) 176 | return true; 177 | } 178 | return false; 179 | } 180 | return false; 181 | 182 | } 183 | 184 | /* 185 | 最麻烦的,有两个拐角的情况 186 | 两个拐角检测可分解为一个拐角检测和水平检测或垂直检测。即: 187 | 188 | 两个拐角检测 = 一个拐角检测 && (水平检测 || 垂直检测) 189 | 190 | 水平、垂直分别穿过 A B 共有四条直线,扫描直线上所有不包含 A B 的点,看是否存在一点 C ,满足以下任意一项: 191 | 192 | A 点至 C 点通过水平或垂直检测,C 点至 B 点可通过一个拐角连接。(图中用 C 表示) 193 | A 点至 C 点可通过一个拐角连接,C 点至 B 点通过水平或垂直连接。(图中用 C 下划线表示) 194 | */ 195 | bool GameMain::turnTwiceCheck(int x1, int y1, int x2, int y2) 196 | { 197 | if(x1 == x2 && y1 == y2) 198 | return false; 199 | //遍历整个数组找合适的拐点 200 | for(int i = 0 ; i < 11; i++){ 201 | for(int j = 0; j < 6; j++){ 202 | //不为空不能作为拐点 203 | if(items[i][j] != NULL) 204 | continue; 205 | //不和被选方块在同一行列的 不能作为拐点 206 | if(i != x1 && i != x2 && j != y1 && j != y2) 207 | continue; 208 | //作为焦点的部分也要过滤掉 209 | if((i == x1 && j == y2)||( i==x2 && j == y1)) 210 | continue; 211 | if(turnOnceCheck(x1,y1,i,j)&& (horizontalCheck(i,j,x2,y2)||verticalCheck(i,j,x2,y2))) 212 | return true; 213 | if(turnOnceCheck(i,j,x2,y2)&&(horizontalCheck(x1,y1,i,j)||verticalCheck(x1,y1,i,j))) 214 | return true; 215 | } 216 | } 217 | return false ; 218 | } 219 | //生成另一个同图片的方块,保证所有方块是偶数个 220 | void GameMain::creatAnotherItem(int index) 221 | { 222 | //构建创造方块的图片 223 | QString str1 =":/img/"+ QString("%1").arg(index)+"_normal.png"; 224 | QString str2 =":/img/"+ QString("%1").arg(index)+"_hover.png"; 225 | QString str3 =":/img/"+ QString("%1").arg(index)+"_selected.png"; 226 | //生成两个随机数,确定新方块的位置 227 | int i = rand()%11 ; 228 | int j = rand()%6 ; 229 | //确定新随机的位置不能有方块 230 | while(items[i][j] != NULL){ 231 | i = rand()%11 ; 232 | j = rand()%6 ; 233 | //一直随机,直到随机到为空的位置 234 | } 235 | //通过新位置,生成新方块 236 | items[i][j] = new MyItem(str1,str2,str3,this); 237 | items[i][j]->setIndex(index); 238 | items[i][j]->move(i*65+100,j*65+100); 239 | connect(items[i][j],SIGNAL(clicked(MyItem*,int)),this,SLOT(itemClicked(MyItem*,int))); 240 | } 241 | 242 | bool GameMain::isVictory() 243 | { 244 | //遍历所有数组,判断数组不为空,直接返回否 245 | for(int i = 0;i < 11; i++) 246 | for(int j = 0; j < 6; j++) 247 | if(items[i][j] != NULL) 248 | return false; 249 | 250 | //所有节点都是空,游戏胜利,返回true 251 | return true; 252 | } 253 | 254 | void GameMain::restart() 255 | { 256 | //重新开始游戏,关闭本窗体进入欢迎界面。 257 | Widget * w = new Widget(); 258 | w->show(); 259 | this->close(); 260 | } 261 | 262 | //重新排序, 263 | /* 264 | * 思路,选中一个方块,然后再随机选择一个不同的方块进行位置交换。 265 | * 把所有的方块都执行这样一次操作 266 | * 可以保证每种方块总数不会变,也可以保证已经消除的地方不会受影响,并实现了随机重新排列 267 | */ 268 | void GameMain::reorder() 269 | { 270 | int randX,randY; 271 | //先确认交换的第一个方块 272 | for(int i = 0; i < 11; i++){ 273 | for(int j = 0; j < 6; j++){ 274 | if(items[i][j] != NULL){ 275 | //随机生成另一个方块的坐标 276 | randX = rand()%11; 277 | randY = rand()%6; 278 | while(items[randX][randY] == NULL ||(randX == i && randY == j)){ 279 | //一直随机知道符合条件的方块 280 | randX = rand()%11; 281 | randY = rand()%6; 282 | } 283 | //位置交换 284 | swapItem(i,j,randX,randY); 285 | } 286 | } 287 | } 288 | } 289 | 290 | //交换两个方块的位置 291 | void GameMain::swapItem(int x1,int y1,int x2,int y2) 292 | { 293 | //交换两个方块的函数 294 | //保证两个方块不能一样 295 | if(x1 == x2 && y1 == y2) 296 | return ; 297 | //保证两个方块不能为空 298 | if(items[x1][y1] == NULL || items[x2][y2] == NULL) 299 | return ; 300 | //记录第一个交换点的原坐标 301 | int tempX = items[x1][y1]->x(); 302 | int tempY = items[x1][y1]->y(); 303 | //把交换点一移动到交换点二的位置上 304 | items[x1][y1]->move(items[x2][y2]->x(),items[x2][y2]->y()); 305 | //把坐标点二移动到坐标点一的位置上 306 | items[x2][y2]->move(tempX,tempY); 307 | //交换回指针的指向 308 | MyItem * tempPtr = items[x1][y1]; 309 | items[x1][y1] = items[x2][y2]; 310 | items[x2][y2] = tempPtr; 311 | 312 | } 313 | 314 | //提示 让计算机进行消除 315 | /* 316 | * 核心思想:把现存的每两个方块都进行一次判断, 317 | * 如果可以连通就执行消除的操作,如果过不是,就不执行,继续循环校验下一组 318 | * 319 | * 320 | */ 321 | void GameMain::prompt() 322 | { 323 | //计算机执行连连看算法 324 | for(int i = 0; i < 11; i++){ 325 | for( int j = 0; j < 6; j++){ 326 | //以上两个for循环,定位第一个选中点 327 | if(items[i][j] != NULL){ 328 | for(int m = 0; m < 11 ; m++){ 329 | for(int n = j; n < 6; n++){ 330 | if(items[m][n] != NULL ){ 331 | //后俩个for循环定位第二个选中点 332 | if(items[i][j]->getIndex() == items[m][n]->getIndex()){ 333 | if(i != m || j != n){//如果两个点图片相同并且不是同一个点 执行消除 334 | if(eraser(i,j,m,n))//如果消除成功 直接返回 335 | return; 336 | else//如果没有,则继续循环 337 | continue; 338 | } 339 | } 340 | } 341 | } 342 | } 343 | } 344 | } 345 | } 346 | } 347 | 348 | //计算机自动消除 349 | bool GameMain::eraser(int x1, int y1, int x2, int y2) 350 | { 351 | if(x1 == x2 && y1 == y2) 352 | return false; 353 | //判断可连通的话,才进行消除 354 | if(canConnect(x1,y1,x2,y2)){ 355 | delete items[x1][y1]; 356 | delete items[x2][y2]; 357 | items[x1][y1] = NULL; 358 | items[x2][y2] = NULL; 359 | this->killTimer(timerId); 360 | //判断胜负逻辑 361 | if(isVictory()){ 362 | TDWidget * victory = new TDWidget(":/img/victory.png",this); 363 | victory->setMoveEnable(false); 364 | victory->move(0,0); 365 | return true; 366 | } 367 | //执行刷新定时器的操作 368 | timerId = this->startTimer(10000); 369 | return true; 370 | } 371 | return false; 372 | } 373 | 374 | void GameMain::exitGame() 375 | { 376 | this->close(); 377 | } 378 | 379 | //定时器的触发函数 380 | void GameMain::timerEvent(QTimerEvent *e) 381 | { 382 | //超时,显示游戏失败的图片 383 | TDWidget * defeat= new TDWidget(":/img/defeat.png",this); 384 | defeat->setMoveEnable(false); 385 | defeat->move(0,0); 386 | //游戏已经结束,就停止定时器。 387 | this->killTimer(timerId); 388 | } 389 | 390 | void GameMain::itemClicked(MyItem *item, int i) 391 | { 392 | //判断如果两个记录值相等,进行相关操作 393 | if(i == currentIndex){ 394 | if(curItem != NULL && canConnect(curItem,item)){ 395 | //如果记录值相等并且不为空,可以进行消除 396 | delete curItem; 397 | delete item; 398 | //把数组中记录的指针置空 399 | for(int i = 0; i < 11; i++){ 400 | for(int j = 0; j < 6 ; j++ ){ 401 | if(items[i][j] == item||items[i][j] == curItem) 402 | items[i][j] = NULL; 403 | } 404 | } 405 | curItem = NULL; 406 | item = NULL; 407 | this->killTimer(timerId); 408 | //判断胜负逻辑 409 | if(isVictory()){ 410 | TDWidget * victory = new TDWidget(":/img/victory.png",this); 411 | victory->setMoveEnable(false); 412 | victory->move(0,0); 413 | return ; 414 | } 415 | //执行刷新定时器的操作 416 | timerId = this->startTimer(10000); 417 | 418 | return ; 419 | } 420 | } 421 | //如果没有消除,赋值保留记录值 422 | curItem = item; 423 | currentIndex = i; 424 | 425 | } 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | -------------------------------------------------------------------------------- /PictureMatching3/gamemain.h: -------------------------------------------------------------------------------- 1 | #ifndef GAMEMAIN_H 2 | #define GAMEMAIN_H 3 | #include "ThreeDog/tdwidget.h" 4 | #include "ThreeDog/tdpushbutton.h" 5 | #include "ThreeDog/tdmenubutton.h" 6 | #include "myitem.h" 7 | #include 8 | #include "widget.h" 9 | 10 | class GameMain : public TDWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit GameMain(QWidget *parent = 0); 16 | //生成所有的方块 17 | void createItems(); 18 | //判断可以连通的函数 19 | bool canConnect(MyItem *item1,MyItem *item2); 20 | //重载一个连通函数接口 21 | bool canConnect(int x1,int y1,int x2,int y2); 22 | //判断不同请况下 可以连通的函数 23 | bool horizontalCheck(int x1,int y1,int x2,int y2);//横向校验 24 | bool verticalCheck(int x1,int y1,int x2,int y2);//纵向校验 25 | bool turnOnceCheck(int x1,int y1,int x2,int y2);//一个拐点的校验 26 | bool turnTwiceCheck(int x1,int y1, int x2,int y2);//两个拐点的校验 27 | //创建对应的另一个方块 28 | void creatAnotherItem(int index); 29 | //判断是否胜利 30 | bool isVictory(); 31 | 32 | //重新开始 33 | void restart(); 34 | //重新排列 35 | void reorder(); 36 | //交换方块的函数 37 | void swapItem(int x1,int y1,int x2,int y2); 38 | //提示 39 | void prompt(); 40 | //自动消除方块的函数 41 | bool eraser(int x1,int y1,int x2,int y2); 42 | //退出 43 | void exitGame(); 44 | 45 | 46 | protected: 47 | void timerEvent(QTimerEvent *e); 48 | 49 | public slots: 50 | //获取被点击方块信息的槽函数 51 | void itemClicked(MyItem *item ,int i); 52 | private: 53 | //存放所有方块的数组 54 | MyItem * items[11][6]; 55 | //保存上一次点击的index 56 | int currentIndex; 57 | MyItem * curItem; 58 | //定时器ID 59 | int timerId; 60 | }; 61 | 62 | #endif // GAMEMAIN_H 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /PictureMatching3/img.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | img/1_hover.png 4 | img/1_normal.png 5 | img/1_selected.png 6 | img/2_hover.png 7 | img/2_normal.png 8 | img/2_selected.png 9 | img/3_hover.png 10 | img/3_normal.png 11 | img/3_selected.png 12 | img/4_hover.png 13 | img/4_normal.png 14 | img/4_selected.png 15 | img/5_hover.png 16 | img/5_normal.png 17 | img/5_selected.png 18 | img/6_hover.png 19 | img/6_normal.png 20 | img/6_selected.png 21 | img/7_hover.png 22 | img/7_normal.png 23 | img/7_selected.png 24 | img/8_hover.png 25 | img/8_normal.png 26 | img/8_selected.png 27 | img/9_hover.png 28 | img/9_normal.png 29 | img/9_selected.png 30 | img/10_hover.png 31 | img/10_normal.png 32 | img/10_selected.png 33 | img/11_hover.png 34 | img/11_normal.png 35 | img/11_selected.png 36 | img/12_hover.png 37 | img/12_normal.png 38 | img/12_selected.png 39 | img/13_hover.png 40 | img/13_normal.png 41 | img/13_selected.png 42 | img/14_hover.png 43 | img/14_normal.png 44 | img/14_selected.png 45 | img/begin_hover.png 46 | img/begin_normal.png 47 | img/begin_press.png 48 | img/daohang.png 49 | img/defeat.png 50 | img/exit_hover.png 51 | img/exit_normal.png 52 | img/exit_press.png 53 | img/game_main.png 54 | img/game_main_with_logo.png 55 | img/logo.png 56 | img/prompt_hover.png 57 | img/prompt_normal.png 58 | img/prompt_press.png 59 | img/reorder_hover.png 60 | img/reorder_normal.png 61 | img/reorder_press.png 62 | img/restart_hover.png 63 | img/restart_normal.png 64 | img/restart_press.png 65 | img/victory.png 66 | img/welcome.png 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /PictureMatching3/img/10_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/10_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/10_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/10_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/10_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/10_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/11_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/11_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/11_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/11_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/11_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/11_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/12_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/12_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/12_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/12_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/12_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/12_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/13_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/13_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/13_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/13_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/13_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/13_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/14_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/14_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/14_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/14_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/14_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/14_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/1_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/1_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/1_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/1_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/1_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/1_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/2_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/2_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/2_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/2_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/2_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/2_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/3_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/3_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/3_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/3_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/3_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/3_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/4_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/4_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/4_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/4_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/4_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/4_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/5_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/5_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/5_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/5_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/5_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/5_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/6_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/6_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/6_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/6_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/6_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/6_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/7_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/7_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/7_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/7_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/7_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/7_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/8_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/8_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/8_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/8_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/8_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/8_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/9_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/9_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/9_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/9_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/9_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/9_selected.png -------------------------------------------------------------------------------- /PictureMatching3/img/begin_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/begin_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/begin_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/begin_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/begin_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/begin_press.png -------------------------------------------------------------------------------- /PictureMatching3/img/daohang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/daohang.png -------------------------------------------------------------------------------- /PictureMatching3/img/defeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/defeat.png -------------------------------------------------------------------------------- /PictureMatching3/img/exit_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/exit_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/exit_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/exit_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/exit_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/exit_press.png -------------------------------------------------------------------------------- /PictureMatching3/img/game_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/game_main.png -------------------------------------------------------------------------------- /PictureMatching3/img/game_main_with_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/game_main_with_logo.png -------------------------------------------------------------------------------- /PictureMatching3/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/logo.png -------------------------------------------------------------------------------- /PictureMatching3/img/prompt_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/prompt_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/prompt_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/prompt_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/prompt_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/prompt_press.png -------------------------------------------------------------------------------- /PictureMatching3/img/reorder_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/reorder_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/reorder_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/reorder_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/reorder_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/reorder_press.png -------------------------------------------------------------------------------- /PictureMatching3/img/restart_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/restart_hover.png -------------------------------------------------------------------------------- /PictureMatching3/img/restart_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/restart_normal.png -------------------------------------------------------------------------------- /PictureMatching3/img/restart_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/restart_press.png -------------------------------------------------------------------------------- /PictureMatching3/img/victory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/victory.png -------------------------------------------------------------------------------- /PictureMatching3/img/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/PictureMatching3/img/welcome.png -------------------------------------------------------------------------------- /PictureMatching3/main.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | Widget w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /PictureMatching3/myitem.cpp: -------------------------------------------------------------------------------- 1 | #include "myitem.h" 2 | 3 | MyItem::MyItem(const QString pic_n, const QString pic_h, const QString pic_s, QWidget *parent) 4 | :TDMenuButton(pic_n,pic_h,pic_s,parent) 5 | { 6 | //鼠标一点击,就执行回调函数 7 | this->setCallback(this,my_selector(MyItem::itemClicked)); 8 | } 9 | 10 | void MyItem::setIndex(const int i) 11 | { 12 | this->index = i; 13 | } 14 | 15 | int MyItem::getIndex() 16 | { 17 | return this->index; 18 | } 19 | 20 | void MyItem::itemClicked() 21 | { 22 | //在此发送信号,包含本对象的数据 23 | emit clicked(this,this->index); 24 | } 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /PictureMatching3/myitem.h: -------------------------------------------------------------------------------- 1 | #ifndef MYITEM_H 2 | #define MYITEM_H 3 | #include "ThreeDog/tdmenubutton.h" 4 | 5 | class MyItem : public TDMenuButton 6 | { 7 | Q_OBJECT 8 | public: 9 | explicit MyItem(const QString pic_n,const QString pic_h,const QString pic_s,QWidget *parent = 0); 10 | //设置此条目的标号 11 | void setIndex(const int i); 12 | //获取此条目的标号 13 | int getIndex(); 14 | signals: 15 | void clicked(MyItem * item, int index); 16 | 17 | private : 18 | //捕获点击信号进行转发 19 | void itemClicked(); 20 | int index ;//标识不同图片的变量 21 | }; 22 | 23 | #endif // MYITEM_H 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /PictureMatching3/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include 3 | #include 4 | Widget::Widget(QWidget *parent) 5 | : TDWidget(":/img/welcome.png",parent) 6 | { 7 | //生成开始游戏的按钮 8 | //参数(三态图片路径 + 父控件指针) 9 | TDPushButton *beginBtn = new TDPushButton( 10 | ":/img/begin_normal.png", 11 | ":/img/begin_hover.png", 12 | ":/img/begin_press.png",this); 13 | //把按钮放置在指定位置 14 | beginBtn->move(330,450); 15 | //给按钮指定一个触发的函数 16 | beginBtn->setCallback \ 17 | (this,my_selector(Widget::startGame));//回调 18 | } 19 | 20 | void Widget::startGame() 21 | { 22 | //qDebug()<<"start game!"; 23 | //在此函数中实现页面跳转 24 | //生成新的窗体 游戏主界面 25 | GameMain *gm = new GameMain(); 26 | //显示主界面 27 | gm->show(); 28 | this->close(); 29 | 30 | } 31 | 32 | Widget::~Widget() 33 | { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /PictureMatching3/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | //游戏开始界面 4 | #include 5 | #include "ThreeDog/tdwidget.h" 6 | #include "ThreeDog/tdpushbutton.h" 7 | #include "gamemain.h" 8 | 9 | class Widget : public TDWidget 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | Widget(QWidget *parent = 0); 15 | //开始按钮点击触发的函数 16 | void startGame(); 17 | ~Widget(); 18 | }; 19 | 20 | #endif // WIDGET_H 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 名称: 3 | - PictureMatching 4 | 5 | ## 软件简介 6 | - 一个王者荣耀风格的连连看游戏,实现了连连看的基本算法和功能。超过十秒没有消除就会游戏失败。全部消除游戏成功。提供重新开始、重新排列、提示(会直接消除两个方块)退出游戏的功能。 7 | 8 | ## 说明: 9 | - 开发平台: Windows 7 X64. 10 | - 开发环境: Qt 5.7 11 | - 游戏中所有的代码以及资源文件均已开源,可自行下载,欢迎更多的学习交流。 12 | 13 | ## 用法: 14 | - 使用Qt打开项目.pro文件,编译运行。 15 | 16 | ## 项目截图: 17 | ![项目截图1](show/show_1.jpg) 18 | ![项目截图2](show/show_2.jpg) 19 | ![项目截图3](show/show_3.jpg) 20 | ![项目截图4](show/show_4.jpg) 21 | 22 | ## 开源协议: 23 | - 雪碧软件协议 24 | -------------------------------------------------------------------------------- /show/show_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/show/show_1.jpg -------------------------------------------------------------------------------- /show/show_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/show/show_2.jpg -------------------------------------------------------------------------------- /show/show_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/show/show_3.jpg -------------------------------------------------------------------------------- /show/show_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheThreeDog/PictureMatching/8d6b93adf5b67016b8deb5b2820b189e25f78314/show/show_4.jpg --------------------------------------------------------------------------------