QT汉诺塔项目详解:多线程动画

关注QT坐标,多线程动画中坐标的变化。汉诺塔都是吃要的。

我的汉诺塔新解:一种更美的描述。

http://blog.csdn.net/weixin_39788534/article/details/79376528

项目地址:

https://github.com/zhuimengshaonian66/hannuo

2018年 追梦少年 QQ:1131052403 —— Dreamer QQ : 1131052403

开源的狂热爱好者,代码风骚,效率恐怖 —— Open source enthusiasts, code coquettish, efficient horror灾难总是接踵而至,如果我失败了,只能说明我不过是如此程度的男人。

界面是在ui手动添加的,按钮的加载是根据文本框的数字来的

《QT汉诺塔项目详解:多线程动画》

《QT汉诺塔项目详解:多线程动画》

思路就是,ABC三条线就是三个栈,移动时就把按钮压进去。

先看汉诺塔的核心代码,新开了一个线程操作的线程中

 C.push(A.pop());就是按钮在三个栈的出栈与压栈

void MyThread::run()
{
    move(*n, *A, *B, *C);
    btnStart->setEnabled(true);
}
void MyThread::move(int n, ABC &A, ABC &B, ABC &C)
{
    if (n == 0)
    {
        return;
    }
    move(n - 1, A, C, B);
    QThread::msleep(500);
    /// windows下多线程操作GUI会出问题,只能用这个
    e.processEvents();
    C.push(A.pop());
    move(n - 1, B, A, C);
}

下面的类就是模拟一个栈,最关键的是在push函数中,要重新对于按钮进行定位。非常关键。

#ifndef ABC_H
#define ABC_H
#include<stack>
#include<QPushButton>
using std::stack;
class ABC
{
public:
    ABC(int _xmid, int _bottom);
    QPushButton * pop();
    void push(QPushButton * btn);
    unsigned int size();
    void clear();
private:
    stack<QPushButton *> btns;
    int xmid;
    int bottom;
};
#endif // ABC_H



#include "abc.h"
ABC::ABC(int _xmid, int _bottom)
    :xmid(_xmid), bottom(_bottom)
{
}
void ABC::push(QPushButton * btn)
{
    if (!btn)
    {
        return;
    }
    btns.push(btn);
    QSize size = btn->size();
    btn->setGeometry(xmid - size.width() / 2, bottom - btns.size() * 20, size.width(), size.height());
    //btn->show();
}
QPushButton * ABC::pop()
{
    QPushButton * btn = btns.top();
    btns.pop();
    return btn;
}
unsigned int ABC::size()
{
    return btns.size();
}
void ABC::clear()
{
    while (btns.size())
    {
        QPushButton * btn = btns.top();
        btns.pop();
        delete btn;
    }
}

初始化三个栈的时候,就要把他们的坐标记录起来:你可能会问,怎么传递这个坐标,这里告诉大家一个不传的秘法,就是通过鼠标的移动事件来轻松的定位到三条线的坐标。

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    A(150, 420),
    B(380, 420),
    C(610, 420),
    t(NULL)
{
    ui->setupUi(this);
}

初始化按钮,setGeometry函数是这个项目的关键,num*30是按钮的宽度,20是按钮的高度。

void Widget::on_btnStart_clicked()
{
    bool isok;
    unsigned int num = ui->txtNum->text().toUInt(&isok);
    if (!isok)
    {
        return;
    }
    ui->btnStart->setEnabled(false);
    A.clear();
    B.clear();
    C.clear();
    this->n = num;
    while (num)
    {
        QPushButton * btn = new QPushButton(this);
        btn->setText(QString::number(num));
        btn->setGeometry(0, 0, num * 30, 20);
        A.push(btn);
        btn->show();
        num--;
    }
    delete t;
    t = new MyThread(&n, &A, &B, &C, ui->btnStart);
    t->run();
}

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/weixin_39788534/article/details/79602812
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞