При работе с Qt встала задача: как правильно организовать доступ к данным родительской формы из дочерней формы. Был выбран вариант передачи указателя на экземпляр данной формы в конструктор дочерней формы. В этом случае у Вас может возникнуть следующая проблема. Для родительской формы вы подключаете заголовочный файл определения класса дочерней формы. Но и дочернему классу нужно сообщить о классе (типе) родительской формы. Если подключить заголовочный файл определения класса родительской формы, то возникнет ситуация циклического подключения этих заголовочных файлов. Чтобы этого избежать, необходимо воспользоваться техникой "опережающего определения" (forward declaration):
bar.h
#include "foo.h"
class bar {
public:
bar();
};
bar.cpp
bar::bar() {
foo f ();
// work with object f
}
foo.h
class bar; // forward declaration
class foo {
public:
foo(bar* obj); // pointer or a reference
};
foo.cpp
#include "bar.h"
#include "foo.h"
foo::foo(bar* obj) {
// work with pointer obj
}
Ниже приведен пример данного подхода, в котором дочерняя форма при отрисовке таблицы со списком элементов обращается к соответствующему списку родительской формы.
item.h
#ifndef ITEM
#define ITEM
#include <QString>
class Item {
private:
int id;
QString description;
public:
Item(int id, QString description) : id(id), description(description) {}
void setId(int id) {
this->id = id;
}
int getId() const {
return id;
}
void setDescription(QString description) {
this->description = description;
}
QString getDescription() const {
return description;
}
};
#endif
mainwindow.h
#ifndef MAINWINDOW
#define MAINWINDOW
#include <QMainWindow>
#include "itemswindow.h"
#include "item.h"
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget* wgt = 0);
QList<Item> itemList;
public slots:
void slotItems();
};
#endif
mainwindow.cpp
#include <QtWidgets>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget* wgt) : QMainWindow(wgt) {
QMenu* menu = new QMenu("Menu");
menu->addAction("Exit", qApp, SLOT(quit()));
menuBar()->addMenu(menu);
// central widget
QWidget* centralWidget = new QWidget;
QVBoxLayout* buttonsWidgetLayout = new QVBoxLayout(centralWidget);
buttonsWidgetLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
QPushButton* itemsBttn = new QPushButton("Items");
itemsBttn->setFixedWidth(150);
buttonsWidgetLayout->addWidget(itemsBttn);
connect(itemsBttn, SIGNAL(clicked()), SLOT(slotItems()));
setCentralWidget(centralWidget);
setWindowTitle("MainWindow");
// for testing
itemList.append(Item(1, "First item"));
itemList.append(Item(2, "Second item"));
itemList.append(Item(3, "Third item"));
itemList.append(Item(4, "Fourth item"));
itemList.append(Item(5, "Fifth item"));
}
void MainWindow::slotItems() {
ItemsWindow* itemsWindow = new ItemsWindow(this, this);
itemsWindow->exec();
delete itemsWindow;
}
itemswindow.h
#ifndef ITEMSWINDOW
#define ITEMSWINDOW
#include <QtWidgets>
#include <item.h>
class MainWindow;
class ItemsWindow : public QDialog {
Q_OBJECT
private:
QTableWidget* table;
public:
ItemsWindow(MainWindow* mw = 0, QWidget* wgt = 0);
};
#endif
itemswindow.cpp
#include "mainwindow.h"
#include "itemswindow.h"
ItemsWindow::ItemsWindow(MainWindow* mw, QWidget* wgt) :
QDialog(wgt, Qt::WindowTitleHint | Qt::WindowCloseButtonHint) {
QVBoxLayout* verticalLayout = new QVBoxLayout;
QHBoxLayout* horizontalBottomLayout = new QHBoxLayout;
QPushButton* okBttn = new QPushButton("&OK");
okBttn->setFixedWidth(60);
connect(okBttn, SIGNAL(clicked()), SLOT(accept()));
horizontalBottomLayout->setAlignment(Qt::AlignRight);
horizontalBottomLayout->addWidget(okBttn);
table = new QTableWidget();
table->setColumnCount(2);
QStringList list;
list << "Id" << "Description";
table->setHorizontalHeaderLabels(list);
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
if (mw != NULL && !mw->itemList.empty()) {
int itemsCnt = mw->itemList.count();
table->setRowCount(itemsCnt);
QTableWidgetItem* tableItem = 0;
for (int i = 0; i < itemsCnt; i++) {
Item item = mw->itemList.at(i);
tableItem = new QTableWidgetItem(QString::number(item.getId()));
tableItem->setTextAlignment(Qt::AlignCenter);
table->setItem(i, 0, tableItem);
tableItem = new QTableWidgetItem(item.getDescription());
table->setItem(i, 1, tableItem);
}
}
this->setWindowTitle("Items");
verticalLayout->addWidget(table);
verticalLayout->addLayout(horizontalBottomLayout);
setLayout(verticalLayout);
}
main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char** argv) {
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
Исходники доступны по данной ссылке - source.
C++. Qt5.6. Combobox with checkboxes
На днях работал с замечательной библиотекой Qt. Нужно было добавить возможность выбора элементов по флажкам в выпадающем списке. Вроде тривиальная gui задача, но у меня немного вызвало затруднение. Ниже приведено мое решение. Исходная платформа - Win64.
multilist.h
main.cpp
multilist.h
#ifndef MULTILIST
#define MULTILIST
#include <QtWidgets>
class MultiList : public QComboBox {
Q_OBJECT
private:
QString displayText;
QStandardItemModel *model;
public:
MultiList(QWidget *parent = 0) : QComboBox(parent) {
setEditable(true);
displayText = "";
model = new QStandardItemModel;
slotUpdateText();
connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotUpdate()));
}
void addItem(const QString &text) {
int row = model->rowCount();
QStandardItem* item = new QStandardItem();
item->setText(text);
item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
item->setData(Qt::Unchecked, Qt::CheckStateRole);
model->setItem(row, 0, item);
this->setModel(model);
}
void addItems(const QStringList &texts) {
for (int i = 0; i < texts.count(); i++) {
addItem(texts.at(i));
}
}
QStringList getCheckedItems() const {
QStringList checkedItems;
for (int i = 0; i < model->rowCount(); i++) {
if (model->item(i, 0)->checkState() == Qt::Checked) {
checkedItems << model->item(i, 0)->text();
}
}
return checkedItems;
}
void setCheckedItems(const QStringList &items) {
for (int i = 0; i < items.count(); i++) {
int index = findText(items.at(i));
if (index != -1) {
model->item(index)->setData(Qt::Checked, Qt::CheckStateRole);
}
}
slotUpdate();
}
public slots:
void slotUpdateText() {
lineEdit()->setText(displayText);
}
void slotUpdate() {
displayText = "";
for (int i = 0; i < model->rowCount(); i++) {
if (model->item(i, 0)->checkState() == Qt::Checked) {
displayText = displayText + model->item(i, 0)->text() + "; ";
}
}
QTimer::singleShot(0, this, SLOT(slotUpdateText()));
}
};
#endif
main.cpp
#include "multilist.h"
int main(int argc, char** argv) {
QApplication app(argc, argv);
MultiList *multiList = new MultiList();
multiList->addItems(QStringList() << "One" << "Two" << "Three" << "Four");
multiList->setCheckedItems(QStringList() << "One" << "Two");
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(new QLabel("Select items:"));
layout->addWidget(multiList, 1);
QWidget widget;
widget.setWindowTitle("MultiList example");
widget.setLayout(layout);
widget.show();
return app.exec();
}
Subscribe to:
Posts
(
Atom
)