对于我的GUI我想有两对上下了scrollarea滚动按钮。 第一组按钮应该说scrollarea1工作,第二组按钮应在scrollarea2工作。 我把在scrollarea窗口小部件被称为viewport1和viewport2。 由于这两个都设置按钮也应该这样做(上下滚动),我想我会做两个插槽称为scrollUp和下滚,将处理滚动两个按钮组。 不幸的是,我不能做这项工作,需要一些帮助。 我曾尝试以下:
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));
}
但是,有几个原因此doesn't工作。 我也试过给插槽一些参数,是这样的:
connect(&up,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea1,viewport1)));
connect(&up2,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea2,viewport2)));
但同样,没有更迭。 有谁能够帮助我?
首先,“它不工作”并不意味着什么,这是很难帮助你,如果你不说你得到了什么错误。 然后,还有一些问题。
所有的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()
插槽,它是你的主窗口谁做:
connect(&up, SIGNAL(clicked()), this, SLOT(scrollUp()));
(因为connect
被称为在主窗口的构造this
指向当前主窗口对象)。
此外,在C ++单=
标志表示分配,是否相等的比较使用=='. And
=='. And
sender`是一个函数。
如果以正确的方式来实现你的方法应该工作:
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`.
};
有在你的代码的几个误区:
- 关于信号的发送者:没有一个
QObject
所谓的“ sender
”,而是一种方法QObject * QObject::sender() const;
它返回该信号的发送者的指针。 - 在if条件:你是铸造
QPushButton**
到QPushButton
( (QPushButton) &sender
),你不要比较你的按钮那个东西up(2)
和down(2)
- 在插槽和信号之间的连接:在
scrollUp
和scrollDown
插槽不属于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) {
// [...]
}
// [...]
}
首先插槽可以没有其他参数比信号手吧。 被点击的没有参数,有前槽可以没有参数。
我认为,最简单的方法来检查scrollArea 1或2是否已经集中,并从其中一个应该移动决定。
我还认为,有你的代码中的错误。 不应该这样:
if((QPushButton) &sender = down2)
{
area=scrollArea;
view=viewport;
}
是这样的:
if((QPushButton) &sender = down2)
{
area=scrollArea2;
view=viewport2;
}
首先,这是伪代码。 它不会编译,但它应该包含必要的信息。
我相信这个问题可以通过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
}
}