2

对于我的 GUI,我希望有两对按钮可以上下滚动滚动区域。第一组按钮应该在 scrollarea1 上工作,第二组按钮应该在 scrollarea2 上工作。我放入滚动区域的小部件称为 viewport1 和 viewport2。由于两组按钮都应该执行相同的操作(向上和向下滚动),我想我会制作两个名为 scrollUp 和 scrollDown 的插槽来处理两组按钮的滚动。不幸的是,我无法完成这项工作,需要一些帮助。我尝试了以下方法:

QPushButton up;
QPushButton down;
QPushButton up2;
QPushButton down2;

connect(&up,SIGNAL(clicked()),&up,SLOT(scrollUp()));
connect(&up2,SIGNAL(clicked()),&up,SLOT(scrollUp()));
connect(&down,SIGNAL(clicked()),&down,SLOT(scrollDown()));
connect(&down2,SIGNAL(clicked()),&down,SLOT(scrollDown()));

void MainWindow::scrollDown()
{
QScrollArea area;
QWidget view;

if((QPushButton) &sender = down)
{
    area=scrollArea;
    view=viewport;
}
if((QPushButton) &sender = down2)
{
    area=scrollArea;
    view=viewport;
}
int curpos = area.verticalScrollBar()->value();
area.verticalScrollBar()->setValue(curpos+15);
int newpos = area.verticalScrollBar()->value();
QPoint topLeft = area.viewport()->rect().topLeft();
view.move(topLeft.x(),topLeft.y()-(newpos));
}

void MainWindow::scrollUp()
{
QScrollArea area;
QWidget view;

if((QPushButton) &sender = up)
{
    area=scrollArea;
    view=viewport;
}
if((QPushButton) &sender = up2)
{
    area=scrollArea2;
    view=viewport2;
}
int curpos = area.verticalScrollBar()->value();
area.verticalScrollBar()->setValue(curpos-15);
int newpos = area.verticalScrollBar()->value();
QPoint topLeft = area.viewport()->rect().topLeft();
view.move(topLeft.x(),topLeft.y()-(newpos));
}

但这不起作用有几个原因。我还尝试为插槽提供一些参数,例如:

connect(&up,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea1,viewport1)));
connect(&up2,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea2,viewport2)));

但同样,没有成功。有谁能够帮助我?

4

4 回答 4

7

首先,“它不起作用”并不意味着什么,如果你不说你得到了什么错误,很难帮助你。然后,问题很少。

所有 QObject 的派生类都是不可复制的,这意味着你不能这样做

QWidget a;
QWidget b;
b = a; // Wrong

您应该使用指针(或者可能是引用)。

QWidget a;
QWidget * b = new QWidget(...);
QWidget * c;
c = & a; // Ok
c = b; // Ok

那么你的connect电话是错误的:

connect(&up, SIGNAL(clicked()), &up, SLOT(scrollUp()));

第三个参数是拥有插槽的对象。up是一个 QPushButton,它没有scrollUp()插槽,它是你的 MainWindow 做的:

connect(&up, SIGNAL(clicked()), this, SLOT(scrollUp()));

(因为connect在 MainWindow 的构造函数中调用this指向当前 MainWindow 对象)。

同样在 C++ 中,单=号表示赋值,对于相等比较,使用=='. Andsender` 是一个函数。

如果以正确的方式实施,您的方法应该有效:

class MainWindow: public QWidget
{
    QScrollArea * scroll1;
    QScrollArea * scroll2;
    QWidget * view1;
    QWidget * view2;
    QPushButton * up1;
    QPushButton * up2;
    QPushButton * down1;
    QPushButton * down2;

public:
    MainWindow()
    {
        // Here initialize member variables.
        ...

        connect(up1, SIGNAL(clicked()), this, SLOT(scrollUp()));
        connect(up2, SIGNAL(clicked()), this, SLOT(scrollUp()));
        connect(down1, SIGNAL(clicked()), this, SLOT(scrollDown()));
        connect(down2, SIGNAL(clicked()), this, SLOT(scrollDown()));
    }

public slots:
    void scrollDown()
    {
        QScrollArea * area;
        QWidget * view;

        if(qobject_cast<QPushButton>(sender()) == down1) {
            area = & scroll1;
            view = & view1;
        } else if(qobject_cast<QPushButton>(sender()) == down2) {
            area = & scroll2;
            view = & view2;
        } else {
            // Error.
        }

        // Now `area` and `view` point to the right widgets.
        ...
    }

    void scrollUp()
    {
        // The same as before.
    }
};

另一种方法是将实际的滚动指令提取到一个单独的函数中:

class MainWindow: public QWidget
{
    // Same variables as before
    ...

public:
    MainWindow()
    {
        // Here initialize member variables.
        ...

        connect(up1, SIGNAL(clicked()), this, SLOT(scrollUp1()));
        connect(up2, SIGNAL(clicked()), this, SLOT(scrollUp2()));
        connect(down1, SIGNAL(clicked()), this, SLOT(scrollDown1()));
        connect(down2, SIGNAL(clicked()), this, SLOT(scrollDown2()));
    }

public slots:
    void scrollDown(QScrollArea * area, QWidget * view)
    {
        // Here you scroll over `area` and `view`.
    }

    void scrollDown1()
    {
        scrollDown(scroll1, area1);
    }

    void scrollDown2()
    {
        scrollDown(scroll2, area2);
    }

    // Again, the same for `scrollUp`.
};
于 2012-07-04T13:56:21.980 回答
5

您的代码中有几个错误:

  • 关于信号的发送者:没有QObject所谓的“ sender”,而是一个QObject * QObject::sender() const;返回信号发送者指针的方法。
  • 在 if 条件中:您将 aQPushButton**转换为QPushButton( (QPushButton) &sender) 并且您不将该事物与您的按钮up(2)down(2).
  • 在您的插槽和信号之间的连接中:scrollUpscrollDown插槽不属于QPushButton该类,而是属于您的MainWindow类。

最后,你应该这样写:

connect(&up,    SIGNAL(clicked()), this, SLOT(scrollUp()));
connect(&up2,   SIGNAL(clicked()), this, SLOT(scrollUp()));
connect(&down,  SIGNAL(clicked()), this, SLOT(scrollDown()));
connect(&down2, SIGNAL(clicked()), this, SLOT(scrollDown()));

void MainVindow::scrollDown() {
    // [...]

    QPushButton * senderButton = qobject_cast<QPushButton *>(this->sender()); 
    // QPushButton * senderButton = (QPushButton *) this->sender(); works too

    if (senderButton == &down) {
        // [...]
    }

    if (senderButton == &down2) {
        // [...]
    }

    // [...]
}

void MainVindow::scrollUp() {
    // [...]

    QPushButton * senderButton = qobject_cast<QPushButton *>(this->sender());
    // QPushButton * senderButton = (QPushButton *) this->sender(); works too

    if (senderButton == &up) {
        // [...]
    }

    if (senderButton == &up2) {
        // [...]
    }
    // [...]
}
于 2012-07-04T13:38:17.137 回答
0

首先,除了信号传递给它之外,插槽不能有其他参数。Clicked 没有参数,因此插槽可以没有参数。

我认为检查 scrollArea 1 或 2 是否有焦点并决定应该移动哪个最简单的方法。

我也认为你的代码有错误。这不应该:

if((QPushButton) &sender = down2)
{
    area=scrollArea;
    view=viewport;
}

变成这样:

if((QPushButton) &sender = down2)
{
    area=scrollArea2;
    view=viewport2;
}
于 2012-07-04T13:43:52.593 回答
0

首先,这是伪代码。它不会编译,但它应该包含必要的信息。

我相信使用 QSignalMapper 类可以最优雅地解决这个问题。它允许来自多个发送者的无参数信号连接到一个插槽。

在标题中,编写如下内容:

class QSignalMapper;

class MainWindow : public QMainWindow
{

public:
  void init();

public slots:
  void handleScrollButtons(int id);

private:
enum { ScrollUp1, ScrollDown1, ScrollUp2, ScrollDown2 } // just makes it more convenient to use

QSignalMapper *m_scrollbuttonhandler;
}

在源文件中,写这样的东西

#include <QSignalMapper>

void MainWindow::init()
{
  m_scrollbuttonhandler = new QSignalMapper(this);
  m_scrollbuttonhandler->setMapping(scrollup1button, ScrollUp1);
  m_scrollbuttonhandler->setMapping(scrolldown1button, ScrollDown1);
  m_scrollbuttonhandler->setMapping(scrollup2button, ScrollUp2);
  m_scrollbuttonhandler->setMapping(scrolldown2button, ScrollDown2);
  connect(scrollup1button, SIGNAL(clicked(bool)), m_scrollbuttonhandler, SLOT(map()));
  connect(scrolldown1button, SIGNAL(clicked(bool)), m_scrollbuttonhandler, SLOT(map()));
  connect(scrollup2button, SIGNAL(clicked(bool)), m_scrollbuttonhandler, SLOT(map()));
  connect(scrolldown2button, SIGNAL(clicked(bool)), m_scrollbuttonhandler, SLOT(map()));

  connect(m_scrollbuttonhandler, SIGNAL(mapped(int)), this, SLOT(handleScrollButtons(int)));
}

void MainWindow::handleScrollButtons(int id)
{
  switch (id)
  {
    case ScrollUp1:
    // stuff to do for scrollup1button
    case ScrollDown1:
    // stuff to do for scrolldown1button
    case ScrollUp2:
    // stuff to do for scrollup2button
    case ScrollDown2:
    // stuff to do for scrolldown2button
  }
}
于 2016-06-17T05:47:42.883 回答