Qt - 重新加载小部件内容
Posted
技术标签:
【中文标题】Qt - 重新加载小部件内容【英文标题】:Qt - reloading widget contents 【发布时间】:2010-03-08 15:27:46 【问题描述】:我正在尝试通过添加一个按钮来修改fridge magnets example,该按钮将重新加载绘制可拖动标签的小部件,反映对其读取的文本文件所做的任何更改。我定义了另一个包含按钮和 DragWidget 对象的类,所以在 main() 中会有这个类的实例而不是 DragWidget:
class wrapWidget: public QWidget
Q_OBJECT
public:
wrapWidget();
;
wrapWidget::wrapWidget()
QGridLayout *gridlayout = new QGridLayout();
DragWidget *w = new DragWidget();
QPushButton *b = new QPushButton("refresh");
gridlayout ->addWidget(w,0,0);
gridlayout ->addWidget(b,1,0);
setLayout(gridlayout );
connect(b,SIGNAL(clicked()),w,SLOT(draw()));
连接调用是我尝试刷新的地方。在最初的冰箱贴示例中,所有的标签绘制代码都在 DragWidget 类的构造函数中。我将该代码移到了一个名为“draw()”的公共方法中,并从构造函数中调用了该方法。下面是 DragWidget 的定义和实现:
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDragEnterEvent;
class QDropEvent;
QT_END_NAMESPACE
class DragWidget : public QWidget
public:
DragWidget(QWidget *parent = 0);
public slots:
void draw();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void mousePressEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
;
DragWidget::DragWidget(QWidget *parent)
: QWidget(parent)
draw();
QPalette newPalette = palette();
newPalette.setColor(QPalette::Window, Qt::white);
setPalette(newPalette);
setMinimumSize(400, 100);//qMax(200, y));
setWindowTitle(tr("Fridge Magnets"));
setAcceptDrops(true);
void DragWidget::draw()
QFile dictionaryFile(":/dictionary/words.txt");
dictionaryFile.open(QFile::ReadOnly);
QTextStream inputStream(&dictionaryFile);
int x = 5;
int y = 5;
while (!inputStream.atEnd())
QString word;
inputStream >> word;
if (!word.isEmpty())
DragLabel *wordLabel = new DragLabel(word, this);
wordLabel->move(x, y);
wordLabel->show();
wordLabel->setAttribute(Qt::WA_DeleteOnClose);
x += wordLabel->width() + 2;
if (x >= 245)
x = 5;
y += wordLabel->height() + 2;
我认为也许调用 draw() 作为插槽就足以重新加载标签,但它不起作用。将 draw() 调用放在小部件的重写 paintEvent() 中而不是构造函数中也没有奏效,程序最终会陷入无限循环。
我所做的显然不是正确的做法,那我应该怎么做呢?
【问题讨论】:
【参考方案1】:我的快速猜测是,您没有在 dragwidget.h 头文件中添加 Q_OBJECT 宏,没有生成 DragWidget 类的 moc 文件,并且连接失败并出现“no such slot as draw()”错误。
将“CONFIG += 控制台”添加到 .pro 文件可能也是一个好主意 - 您会看到所有警告消息(例如关于连接错误的警告消息),因此跟踪此类错误会更容易。您还可以检查连接的返回值。
【讨论】:
确实,我在项目的 .pro 文件中添加了 CONFIG+=console 东西,当我运行程序时,它显示“没有像 draw() 这样的插槽”错误。 dragwidget.h 头文件大部分与原始示例中的一样,它没有 Q_OBJECT 宏。当我将它添加到代码中时,它发出了这个错误:“collect2:ld 返回 1 退出状态”。将 Q_OBJECT 宏添加到我的自定义 wrapwidget.h 标头中并没有导致任何不同,但仍然会发出相同的错误。 Q_OBJECT 宏扩展为声明所有信号/插槽的魔法所需的方法。这些方法的定义由 moc.exe 程序生成在单独的文件中。您不必自己调用它,qmake 为每个带有 Q_OBJECT 宏的头文件添加了对 makefile 的正确调用。为什么会出现链接器错误? Q_OBJECT 扩展为声明,但未生成定义,因为您在添加 Q_OBJECT 后未运行 qmake,并且未使用对 DragWidget 类的 moc.exe 调用更新 makefile。另外,请确保将 draw() 声明为公共插槽,而不仅仅是公共方法。 为了完整起见,我已经添加了 DragWidget 的其余代码。我还在我的自定义 wrapwidget 类上添加了 Q_OBJECT 宏(但正如我之前所说,它没有导致任何可见的更改),并省略了我在原始示例中没有更改的所有内容。您可以看到我确实将 draw() 声明为公共插槽。我正在使用 Qt Creator 编辑和编译我的代码,所以它不可能是 qmake 问题,除非我不知道 Qt Creator 存在问题。 插槽在 DragWidget 类中,因此 Q_OBJECT 应该在 DragWidget 类中,而不是在 wrapWidget 类中(尽管通常建议将 Q_OBJECT 宏添加到所有 QObject 子类以避免您遇到的问题现在)。 我不知道是不是这个问题。未修改的示例工作正常,原始 DragWidget 声明中没有 Q_OBJECT 宏(但是,原始代码中没有插槽)。除了将一些代码从构造函数重新定位到新创建的 draw() 槽之外,我没有更改 DragWidget 类中的任何内容。将宏添加到 DragWidget 类声明中会出现此错误:collect2: ld returned 1 exit status。显然有些东西不允许我添加那个类的宏,也许它与那个命名空间的东西有关?【参考方案2】:我注意到你是这样打开文件的:
QFile dictionaryFile(":/dictionary/words.txt");
注意文件名以“:”开头,表示该文件将从你的qrc资源包中读取,而不是从你的本地磁盘中读取。所以如果你对words.txt做了修改,下次编译qrc文件时才会被代码读取。所以你一定知道如何解决它,对吧?祝你好运:)
【讨论】:
正在读取文件,我在再次运行程序之前更改了它,我可以看到标签不同。问题是在程序运行时重绘标签,它说没有这样的插槽 QWidget::draw()。 现在我已经让 draw() 工作了,我确实必须更改文件名。我将其更改为“../words.txt”,现在它读取了正确的文件。阅读一些关于 qrc 文件的信息,似乎资源在最终的可执行文件中被“编译”,但我猜这对于经常修改的文件不一定有好处以上是关于Qt - 重新加载小部件内容的主要内容,如果未能解决你的问题,请参考以下文章