QTimer。如果插槽比信号更多参数怎么办?

时间:2013-05-01 17:41:20

标签: qt signals slot qtimer

我正在写一个游戏。通过滴答计时器应该工作这个插槽。

void game_process::animate_cell(MainWindow* m, const std::string& s, double x,double y, size_t i, size_t j, const std::string& step)
{ 
    painter.begin(m);
    std::string ss("C:\\Users\\Vardan\\GAmes_lines\\res\\red_" + step + ".png");
    ss += s;
    const char* p = ss.c_str();    
    QImage image(p);
    RECT temp = cal

    culate_cell_rect(i, j);
    QRectF target(x, y, image.width(), image.height());
    painter.drawImage(target, image);
    painter.end();
    m->update(x + temp.x0, y + temp.y0, 60, 60);
}
, that's it,

QTimer * timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(render_cell(MainWindow * m,const std :: string& s,double x,double y,size_t i,size_t j,const std :: string& step ))); timer-> start();

但是你可以看到插槽比信号更多的参数,因此信号和插槽机制不起作用。该怎么办? 这里鳕鱼

#include <QDesktopWidget>
#include <QResizeEvent>
#include <QDebug>
#include <QTimer>
#include <QTime> 
#include <phonon/MediaObject>
#include <phonon/MediaSource>
#include <phonon/AudioOutput>
#include <utility>
#include <cassert>

MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    QImage image("C:\\Users\\Vardan\\GAmes_lines\\res\\back_3.png");
    m_width = 1000;
    m_height = 800;
    m_game_width = image.width();
    m_game_height = image.height();
    setFixedSize(m_width, m_height);
    m_click_coords.first = 0;
    m_click_coords.second = 0;
    m_timer_tick = false;
    m_timer_id = 0;        
    setWindowFlags( Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
    m_area_x0_coordinate = (this->width() - image.width())/2;
    m_area_y0_coordinate = (this->height() - image.height())/2;
    m_r = new game_process(m_area_x0_coordinate, m_area_y0_coordinate, image.width()/*+30*/, image.height()/*+30*/, 57);
    m_status = false;     
    Phonon::MediaObject *mediaobject = new Phonon::MediaObject;
    QString filename("C://Users//Vardan//GAmes_lines//music//Casino Ambiance Music.wav");
    mediaobject->setCurrentSource(filename);
    Phonon::AudioOutput *audio = new Phonon::AudioOutput;
    Phonon::createPath(mediaobject,audio);
    mediaobject->play();
    QPixmap pixmap("C:\\Users\\Vardan\\GAmes_lines\\res\\background.png");    
    QPalette palette;    
    palette.setBrush(/*this->backgroundRole()*/QPalette::Background, QBrush(pixmap));
    this->setPalette(palette);

}
MainWindow::MainWindow(std::string& str, QWidget *parent):
    QWidget(parent)
{

}

double MainWindow::get_mouse_click_absolute_x_coordinate() const
{
    return m_area_x0_coordinate;
}

double MainWindow::get_mouse_click_absolute_y_coordinate() const
{
    return m_area_y0_coordinate;
}

void MainWindow::set_mouse_click_absolute_x_coordinate(double x)
{
    m_area_x0_coordinate = x;
}

void MainWindow::set_mouse_click_absolute_y_coordinate(double y)
{
    m_area_y0_coordinate = y;
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    if(m_status == false)
    {
        m_r->game_loop(this);
    }
    else
    {   
        game_process::RECT temp = m_r->calculate_cell_rect(m_click_coords.first, m_click_coords.second);
        int x = m_area_x0_coordinate + temp.x0;
        int y = m_area_y0_coordinate + temp.y0;
        std::pair<double, double> p;
/////////////////////////////////////////////////////////
        start_timer();
//////////////////////////////////////////////////////////
        for(int i = 2; i < 8; ++i)
        {
            char buf[sizeof(int)];
            itoa(i, buf, 10);
            std::string s(buf);            
            m_r->erase_frame(this, x, y);
            while(m_timer_tick == false){}
            p = m_r->draw_frame(this, m_click_coords.first, m_click_coords.second, s.c_str());
            m_timer_tick = false;
        }
        end_timer();            
        m_status = false;
    }        
}

bool MainWindow::delay(int ms)
{
    QTime dieTime = QTime::currentTime().addMSecs(ms);
    while( QTime::currentTime() < dieTime )
    return true;
}

void MainWindow::mousePressEvent (QMouseEvent* e)
{
    qDebug() << "Local:" << e->pos().x();
    qDebug() << "Local:" << e->pos().y();    
    std::pair<double, double> p = m_r->calculate_index_of_the_coordinates(e->pos().x(), e->pos().y(), m_width, m_height);
    if(m_area_x0_coordinate <= e->pos().x() && m_area_y0_coordinate <= e->pos().y()
            && m_area_x0_coordinate + m_game_width >= e->pos().x() && m_area_y0_coordinate + m_game_height >= e->pos().y() )
    {        
        m_status = true;
        m_click_coords.first = p.first;
        m_click_coords.second = p.second;        
        game_process::RECT coords = m_r->calculate_cell_rect(p.first, p.second);                
        Figure* f = m_r->detect_figure_by_index(p.first, p.second);         
        m_r->delete_cluster(this, f);            
    }
    game_process::RECT r;
    qDebug() << "Local:" << p.first;
    qDebug() << "Local:" << p.second;
}

void MainWindow::timerEvent(QTimerEvent *event)
{
    m_timer_tick = true;
} 

void MainWindow::start_timer()
{
    m_timer_id = startTimer(1000 / 30);
}

void MainWindow::end_timer()
{
    killTimer(m_timer_id);
}

bool MainWindow::event(QEvent *e)
{
    switch (e->type())
    {
        case QEvent::WindowActivate:
        case QEvent::WindowDeactivate:
          return true;
    }
    return QWidget::event(e);

}

I noticed that the timer does not start from paintEvent, and I need what he started with paintEvent. What to do?

我按照你的意见调整了代码。

#include "mainwindow.h"
#include "game_process.h"

#include <QPixmap>
#include <QPainter>
#include <QPalette>
#include <QDesktopWidget>
#include <QResizeEvent>
#include <QDebug>
#include <QTimer>
#include <QTime> 
#include <phonon/MediaObject>
#include <phonon/MediaSource>
#include <phonon/AudioOutput>
#include <utility>
#include <cassert>

MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    QImage image("C:\\Users\\Vardan\\GAmes_lines\\res\\back_3.png");
    m_width = 1000;
    m_height = 800;
    m_game_width = image.width();
    m_game_height = image.height();
    setFixedSize(m_width, m_height);
    m_click_coords.first = 0;
    m_click_coords.second = 0;
    m_next_cell = 0;
    m_frame_count = 2;
    m_timer_tick = false;
    m_timer_id = 0;
    m_matrix_size = 0;
    m_timer_flag = false;
    setWindowFlags( Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
    m_area_x0_coordinate = (this->width() - image.width())/2;
    m_area_y0_coordinate = (this->height() - image.height())/2;
    m_r = new game_process(m_area_x0_coordinate, m_area_y0_coordinate, image.width()/*+30*/, image.height()/*+30*/, 57);
    m_status = false;     
    Phonon::MediaObject *mediaobject = new Phonon::MediaObject;
    QString filename("C://Users//Vardan//GAmes_lines//music//Casino Ambiance Music.wav");
    mediaobject->setCurrentSource(filename);
    Phonon::AudioOutput *audio = new Phonon::AudioOutput;
    Phonon::createPath(mediaobject,audio);
    mediaobject->play();
    QPixmap pixmap("C:\\Users\\Vardan\\GAmes_lines\\res\\background.png");    
    QPalette palette;    
    palette.setBrush(/*this->backgroundRole()*/QPalette::Background, QBrush(pixmap));
    this->setPalette(palette);
}

MainWindow::~MainWindow()
{

}

MainWindow::MainWindow(std::string& str, QWidget *parent):
    QWidget(parent)
{

}

double MainWindow::get_mouse_click_absolute_x_coordinate() const
{
    return m_area_x0_coordinate;
}

double MainWindow::get_mouse_click_absolute_y_coordinate() const
{
    return m_area_y0_coordinate;
}

void MainWindow::set_mouse_click_absolute_x_coordinate(double x)
{
    m_area_x0_coordinate = x;
}

void MainWindow::set_mouse_click_absolute_y_coordinate(double y)
{
    m_area_y0_coordinate = y;
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    static int  ind = 0;
    if(m_status == false && m_timer_tick != true)
    {
        m_r->game_loop(this);
    }
    else
    {
        std::pair<double, double> p;
        int x = 0;
        int y = 0;

        static int s = m_r->get_close_map_size();
        static std::vector<std::pair<int, int> > v = m_r->get_close_map_indexes();
        if(m_frame_count >= 7)
        {
            m_frame_count = 2;            
            ++m_next_cell;
            if(m_next_cell <= v.size())
            {
                game_process::RECT temp = m_r->calculate_cell_rect(v[m_next_cell].second, v[m_next_cell].first);
                x = m_area_x0_coordinate + temp.x0;
                y = m_area_y0_coordinate + temp.y0;
                m_x = x;
                m_y = y;
            }
        }
        if(m_next_cell == 0)
        {
            game_process::RECT temp = m_r->calculate_cell_rect(v[m_next_cell].second, v[m_next_cell].first);
            x = m_area_x0_coordinate + temp.x0;
            y = m_area_y0_coordinate + temp.y0;
            m_x = x;
            m_y = y;
        }
        if(m_frame_count < 7 && m_next_cell < v.size())
        {
            char buf[sizeof(int)];
            itoa(m_frame_count, buf, 10);
            std::string s(buf);
            m_r->erase_frame(this, x, y);
            p = m_r->draw_frame(this, v[m_next_cell].second, v[m_next_cell].first, s.c_str());
            m_timer_tick = false;            
            c = true;
        }        
        if(c == false && m_next_cell > v.size() - 1)
        {
            end_timer();
            qDebug()<<"m_x = " << m_x;
            qDebug()<<"m_y = " << m_y;
            qDebug()<<"m_frame_count + 1 = " << m_frame_count + 1;
            qDebug()<<"v.size() = " << v.size();
            m_r->repaint_cells(this);
        }
        m_status = false;
    }    
}

void MainWindow::mousePressEvent (QMouseEvent* e)
{    
    qDebug() << "Local:" << e->pos().x();
    qDebug() << "Local:" << e->pos().y();    
    std::pair<double, double> p = m_r->calculate_index_of_the_coordinates(e->pos().x(), e->pos().y(), m_width, m_height);
    if(m_area_x0_coordinate <= e->pos().x() && m_area_y0_coordinate <= e->pos().y()
            && m_area_x0_coordinate + m_game_width >= e->pos().x() && m_area_y0_coordinate + m_game_height >= e->pos().y() )
    {
        start_timer();
        m_status = true;
        m_click_coords.first = p.first;
        m_click_coords.second = p.second;        
        game_process::RECT coords = m_r->calculate_cell_rect(p.first, p.second);                
        Figure* f = m_r->detect_figure_by_index(p.first, p.second);                 
        m_r->delete_cluster(this, f);
        //this->update(m_area_x0_coordinate + coords.x0, m_area_y0_coordinate + coords.y0, 57, 57);
    }
    game_process::RECT r;
    qDebug() << "Local:" << p.first;
    qDebug() << "Local:" << p.second;
}

void MainWindow::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == m_timer_id)
    {        
        m_timer_tick = true;
        ++m_frame_count;
        if(m_x >=0 && m_y >=0)
        {
            qDebug()<<"m_x  "<<m_x <<"m_y  "<<m_y<<"time |||||| Passed";
            this->update(m_x, m_y, 60, 60);
        }
    }
    else
    {
        QWidget::timerEvent(event);
    }
}

void MainWindow::start_timer()
{
    m_timer_id = startTimer(50);
}

void MainWindow::end_timer()
{    
       killTimer(m_timer_id);     
}

bool MainWindow::event(QEvent *e)
{
    switch (e->type())
    {
        case QEvent::WindowActivate:
        case QEvent::WindowDeactivate:
          return true;
    }
    return QWidget::event(e);

}

这是代码repaint_cells()

void game_process::repaint_cells(MainWindow* m)
{
    Figure* f = 0;    
    for(int i = 0; i < 8; ++i)
    {        
        for(int j = 0; j < 8; ++j)
        {
            if(m_close_list[j][i] == -1)
            {
                f = create_new_figure(j, i);
                m_figures.push_back(f);
                assert(f != 0);
                draw_figure(m, f, i, j);
                m_close_list[j][i] = 0;                
            }
        }
     }
}

enter link description here

两天我无法理解为什么只抽出一个球。剩下的球没有画出来。

2 个答案:

答案 0 :(得分:5)

您有两种主要方法:

  1. 只需定义另一个没有参数的插槽即可调用game_process::render_cell(),然后连接到新插槽。

  2. 如果您使用的是Qt 5,请使用lambda。有关示例,请参阅here。它看起来像这样:connect(timer, &QTimer::timeout, [=](){/*call the function here*/});

  3. 我建议#2。

答案 1 :(得分:0)

我从你的代码片段中看到你正在向你的MainWindow函数传递一个指向render_cell()的指针,我假设它是某种从QObject派生的小部件或类。

在这种情况下,您可以覆盖timerEvent(),它是为每个QObject类定义的,并在此处实现您的游戏循环。这样,render_cell()的参数可以是MainWindow的成员变量,也可以将整个game_process类嵌入MainWindow

另外,我认为这种方法比使用信号要快一些,这对于必须每秒渲染30-60次并更新其他东西的代码来说可能很重要。

有关文档,请参阅http://qt-project.org/doc/qt-4.8/qobject.html#timerEvent

在伪代码中,您可以像这样实现游戏:

class MainWindow : public QWidget
{
  private:
    game_process *game;
    int timer_id;

  public:
    MainWindow(void)
      : QWidget(0),
        game(0),
        timer_id(0)
    {
      game = new game_process;
    }

    void startGame(void)
    {
      timer_id = startTimer(1000 / 30);   // 30 fps
    }

    void endGame(void)
    {
      killTimer(timer_id);
    }

  protected:
    virtual void timerEvent(QTimerEvent *event)
    {
       // update AI
       // update network
       // render game
       game->render_cell(/* params */);
    }

};