C++ 使用QLinkedList循环浏览不同的窗口屏幕

C++ 使用QLinkedList循环浏览不同的窗口屏幕,c++,qt,linked-list,qlinkedlist,C++,Qt,Linked List,Qlinkedlist,对于我的Qt应用程序,我尝试使用一个QLinkedList,用户可以循环浏览用户创建的新窗口屏幕。当用户单击MainWindow上的“新建窗口”按钮时,窗口将动态创建,而MainWindow对象将添加到QLinkedList 我试图使用qlinkedlistierator作为后退和前进按钮,指向上一个屏幕和下一个屏幕。到目前为止,它适用于前进按钮,但对于后退按钮,它会崩溃,如果我在第一个屏幕上单击后退,它也会崩溃 main window.h #ifndef MAINWINDOW_H #defin

对于我的Qt应用程序,我尝试使用一个
QLinkedList
,用户可以循环浏览用户创建的新窗口屏幕。当用户单击
MainWindow
上的“新建窗口”按钮时,窗口将动态创建,而
MainWindow
对象将添加到
QLinkedList

我试图使用
qlinkedlistierator
作为后退和前进按钮,指向上一个屏幕和下一个屏幕。到目前为止,它适用于前进按钮,但对于后退按钮,它会崩溃,如果我在第一个屏幕上单击后退,它也会崩溃

main window.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
\ifndef主窗口
#定义主窗口
#包括
#包括
#包括
#包括
#包括
#包括
名称空间用户界面{
类主窗口;
}
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=0);
~main窗口();
QLinkedList窗口_列表;
私人:
Ui::MainWindow*Ui;
QPushButton*按钮;
主窗口*新窗口;
//添加新窗口
无效输入\新建\窗口();
//前进和后退按钮
无效输入返回按钮();
无效输入\前进\按钮();
无效返回();
无效前进();
void addWindow();
};
#endif//main窗口
main window.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);
}
#包括“mainwindow.h”
#包括“ui_main window.h”
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
这->调整大小(800400);
//---------------------------
//显示按钮
//----------------------------
此->输入返回按钮();
此->输入前进按钮();
此->输入新窗口();
}
MainWindow::~MainWindow()
{
删除用户界面;
}
//将窗口添加到列表的前面
void MainWindow::addWindow()
{
//创建新窗口对象
新建_窗口=新建主窗口();
//将新窗口添加到列表中
窗口列表。追加(新窗口);
//显示新窗口
新建窗口->显示();
}
void主窗口::返回()
{
//返回linkedlist中的上一个窗口
qmutableLinkedListerator i(窗口列表);
if(i.hasPrevious())
{
新建窗口->显示();
这个->隐藏();
}
}
void主窗口::前进()
{
//转到linkedlist中的下一个窗口
qmutableLinkedListerator i(窗口列表);
if(i.hasNext())
{
新建窗口->显示();
这个->隐藏();
}
}
//----------------------------------------------------------
//打开新窗口
//----------------------------------------------------------
void main window::input_new_window()
{
按钮=新的QPushButton(“新窗口”,此按钮);
按钮->设置几何体(QRect(QPoint(10,30),QSize(200,50));
按钮->显示();
QObject::connect(按钮,&QPushButton::按下,此,&MainWindow::addWindow);
}
//--------------------------------------------------------
//使用windows前后移动
//--------------------------------------------------------
void主窗口::输入\返回\按钮()
{
按钮=新的QPushButton(“后退”,此按钮);
按钮->设置几何体(QRect(QPoint(10340),QSize(20050));
按钮->显示();
//带返回屏幕的链接返回按钮
QObject::connect(按钮,&QPushButton::按下,此,&MainWindow::返回);
}
void主窗口::输入\前进\按钮()
{
按钮=新的QPushButton(“前进”,此按钮);
按钮->设置几何体(QRect(QPoint(580340),QSize(200,50));
按钮->显示();
//链接前进按钮与前进屏幕
QObject::connect(按钮,&QPushButton::按下,此,&MainWindow::前进);
}

您使用的是不同的窗口列表:您添加的每个新窗口都有自己的列表,因此循环实际上是不可能的。此外,
new_window
变量作为成员是不必要的,我认为这会给您带来一些麻烦

它用于转发的原因是
new\u window
已经保存了下一个窗口(您在调用
addWindow
方法时分配了它,因此它实际上是下一个窗口)。另一方面,背面也使用了
新窗口(下一个),因此它将无法按预期工作

要解决您的问题,请尝试使用共享的窗口列表,可以是全局列表,也可以在构造每个窗口时传递它

下面的解决方案不是最优雅的,可能有竞争条件,但可以说明我的观点。它使用一个全局窗口列表:每次您想要向前或向后移动时,它都会搜索当前窗口和列表上的周期。此外,我还删除了
new_窗口
member;)

在头文件中

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();
}

// ...
动态创建对象并将其添加到列表中,而不是在堆栈上创建对象:

int main(int argc, char* argv[]) {
    QApplication a(argc, argv);
    auto w = new MainWindow();
    MainWindow::addWindowToList(w);
    w->show();
    return a.exec();
}

  • it
    迭代器实际上是类似STL的迭代器,而不是类似Java的迭代器。没什么大不了的,只是我更熟悉第一个

  • 我无法测试代码,因为现在我无法访问我的开发环境,所以请原谅我的任何打字错误或编译错误


改进

  • 与手动使用
    addWindowToList
    方法不同,您可以在
    main window
    构造函数中执行此操作(
    addWindowToList(this)
    ),因此您只需创建它们,它们就会自动添加
  • 代码没有显示任何关于销毁窗口的内容。关闭/销毁窗口时,应注意将其从列表中删除,否则在循环窗口时会崩溃。与使用构造函数类似,您可以在析构函数上执行此操作,并从列表中删除窗口

再次感谢您的解决方案,我正在尝试编译代码,但它显示了编译器的“(-it)->show();”和“(++it)->show();”的错误
int main(int argc, char* argv[]) {
    QApplication a(argc, argv);
    auto w = new MainWindow();
    MainWindow::addWindowToList(w);
    w->show();
    return a.exec();
}