Для моего приложения Qt я пытаюсь использовать QLinkedList
который пользователь может перемещаться по новым окнам, которые он создал. Окна создаются динамически, когда пользователь нажимает кнопку «Новое окно» на MainWindow
который MainWindow
объект добавлен в QLinkedList
,
Я пытаюсь использовать QLinkedListIterator
чтобы кнопки «Назад» и «Вперед» указывали на предыдущий и следующий экран. Пока что это работает для кнопки «Вперед», но для кнопки «Назад», она падает, и если я нажимаю кнопку «Назад» на первом экране, она также падает.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QTextEdit>
#include <QLinkedList>
#include <QLinkedListIterator>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QLinkedList<MainWindow*> window_list;
private:
Ui::MainWindow *ui;
QPushButton *button;
MainWindow* new_window;
// Add new Window
void input_new_window();
// Forward and back buttons
void input_back_button();
void input_forward_button();
void go_back();
void go_forward();
void addWindow();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(800, 400);
//---------------------------
// Show buttons
//----------------------------
this->input_back_button();
this->input_forward_button();
this->input_new_window();
}
MainWindow::~MainWindow()
{
delete ui;
}
// Add Window to the front of the list
void MainWindow::addWindow()
{
// Create new Window Object
new_window = new MainWindow();
// Add the New Window to the list
window_list.append(new_window);
// Display the New Window
new_window->show();
}void MainWindow::go_back()
{
// Go back to previous window in the linkedlist
QMutableLinkedListIterator<MainWindow*> i(window_list);
if(i.hasPrevious())
{
new_window->show();
this->hide();
}
}void MainWindow::go_forward()
{
// Go forward to next window in the linkedlist
QMutableLinkedListIterator<MainWindow*> i(window_list);
if(i.hasNext())
{
new_window->show();
this->hide();
}
}//----------------------------------------------------------
// Open New Window
//----------------------------------------------------------
void MainWindow::input_new_window()
{
button = new QPushButton("New Window", this);
button->setGeometry(QRect(QPoint(10, 30), QSize(200, 50)));
button->show();
QObject::connect(button, &QPushButton::pressed, this, &MainWindow::addWindow);
}//--------------------------------------------------------
// Going forward and back with windows
//--------------------------------------------------------
void MainWindow::input_back_button()
{
button = new QPushButton("Back", this);
button->setGeometry(QRect(QPoint(10, 340), QSize(200, 50)));
button->show();
// Link back button with going back a screen
QObject::connect(button, &QPushButton::pressed, this, &MainWindow::go_back);
}void MainWindow::input_forward_button()
{
button = new QPushButton("Forward", this);
button->setGeometry(QRect(QPoint(580, 340), QSize(200, 50)));
button->show();
// Link forward button with going forward a screen
QObject::connect(button, &QPushButton::pressed, this, &MainWindow::go_forward);
}
Вы работаете с разными списками окон: каждое новое окно, которое вы добавляете, содержит свой собственный список, поэтому циклирование фактически невозможно. В дополнение new_window
переменная не обязательна в качестве члена, и я думаю, что это создает для вас немного путаницы.
Причина, по которой он работает для форварда, заключается в том, что new_window
уже содержит следующее окно (вы назначили его при вызове addWindow
метод, так что это на самом деле следующий окно). С другой стороны, спина также использует new_window
( следующий), поэтому он не будет работать, как ожидалось.
Чтобы решить вашу проблему, попробуйте использовать общий список окон, может быть глобальный список или передать его при создании каждого окна.
Приведенное ниже решение не является самым элегантным и может иметь гоночные условия, но проиллюстрирует мою точку зрения. Он использует глобальный список окон: каждый раз, когда вы хотите двигаться вперед или назад, он ищет текущее окно и циклически изменяет список. Кроме того, я удалил new_window
член;)
В заголовочном файле
class MainWindow ... {
public:
static void addWindowToList(MainWindow* w);
}
В файле .cpp
// ...
#include <cassert>
namespace {
QLinkedList<MainWindow*> window_list; // global list
}
// ...
void MainWindow::addWindowToList(MainWindow* w)
{
window_list.append(w);
}
void MainWindow::addWindow()
{
addWindowToList(new MainWindow());
go_forward(); // shows new window
}
void MainWindow::go_back()
{
if (window_list.count() == 1) return; // no other windows
if (window_list.first() == this) { // has to go the last one
window_list.back()->show();
} else {
auto it = std::find(window_list.begin(), window_list.end(), this);
assert(it != window_list.end()); // should be in the list
(*(--it))->show();
}
hide();
}
void MainWindow::go_forward()
{
if (window_list.count() == 1) return; // no other windows
if (window_list.back() == this) { // has to go to the first one
window_list.first()->show();
} else {
auto it = std::find(window_list.begin(), window_list.end(), this);
assert(it != window_list.end()); // should be in the list
(*(++it))->show();
}
hide();
}
// ...
Теперь вы также должны добавить самое первое окно в список. Возможно, вы используете шаблон Qt по умолчанию, например:
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Вместо создания объекта в стеке, сделайте это динамически и добавьте его в список:
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
auto w = new MainWindow();
MainWindow::addWindowToList(w);
w->show();
return a.exec();
}
it
итераторы на самом деле QLinkedList::iterator
, и STL-подобный итератор, а не Java-подобный. Ничего страшного, просто я больше знаком с первыми.
Я не смог протестировать код, так как теперь у меня нет доступа к моей среде разработки, поэтому, пожалуйста, прости меня за любую опечатку или ошибку компиляции.
улучшения
addWindowToList
метод вручную, вы можете сделать это в MainWindow
вместо конструктора (addWindowToList(this)
) так что вам нужно только создать их, и они будут добавлены автоматически.Других решений пока нет …