5

終了ボタンとインポート ボタンの 2 つのボタンを含むアプリを Qt で作成しました。インポート ボタンを押すと、画面上のスクロール領域にボタンのリストが表示されます (ファイル loggers.csv にはデータ 1;2;3;4;5; が含まれます)。

すべて正常に動作しますが、終了ボタン (もちろんすべてを閉じる必要があります) を押すと、アプリは適切に停止しません (Qt の停止ボタンはまだアクティブで、再生ボタンはアクティブではありません)。デバッガーを実行して終了ボタンを押すと、次のエラーが表示されます: RtlFreeHeap に無効なアドレスが指定されました ( 0ADF0000, 0028FE40 )。誰でも私を助けることができますか?

主要

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;

    w.showFullScreen();

    return a.exec();
}

Mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtGui>
#include "logger.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QPushButton exit_btn;
    QPushButton import_btn;

private slots:

    void createMenus();
    void exit();
    void import();

private:

    int window_width;
    int window_height;

    int numLoggers;
    int numSelected;

    QVector<Logger*> loggers;

    QScrollArea * scroll_area;

    QVBoxLayout scrollLayout;

    QWidget viewport;

    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

メインウィンドウ.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QtGui"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    window_width = QApplication::desktop()->width();
    window_height = QApplication::desktop()->height();

    createMenus();

    connect(&exit_btn,SIGNAL(clicked()),this,SLOT(exit()));
    connect(&import_btn,SIGNAL(clicked()),this,SLOT(import()));
}

MainWindow::~MainWindow()
{
   delete ui;
}

void MainWindow::createMenus()
{
    import_btn.setParent(ui->centralWidget);
    import_btn.setGeometry(400,300,100,100);
    import_btn.setText("IMPORT");

    exit_btn.setText("EXIT");
    exit_btn.setParent(ui->centralWidget);
    exit_btn.setGeometry(window_width-50,12,32,32);

    viewport.setLayout(&scrollLayout);
    viewport.resize(0,0);

    scroll_area = new QScrollArea(ui->centralWidget);
    scroll_area->setGeometry(0,66,317,window_height-116);
    scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    scroll_area->setWidget(&viewport);
    scroll_area->setGeometry(0,97,317,window_height-228);

    scrollLayout.setMargin(0);
    scrollLayout.setSpacing(0);
}

void MainWindow::exit()
{
    close();
    qApp->quit();
}

void MainWindow::import()
{
    numSelected=0;

    QFile f("Loggers3.csv");

    if (f.open(QIODevice::ReadOnly))
    {
        numLoggers=0;

        QString data;
        data = f.readAll();
        QStringList vals = data.split(';');

        while(vals.size()>=1)
        {
            Logger * logger = new Logger;

            logger->setNumber(vals[0].toInt());
            vals.removeAt(0);

            loggers<<logger;

            numLoggers++;
        }
        f.close();


        for(int i=0; i<numLoggers;i++)
        {
            loggers[i]->createButtons();
            scrollLayout.addWidget(loggers[i]->button);
        }

        viewport.resize(367,numLoggers*60);
    }
}

logger.h

#ifndef LOGGER_H
#define LOGGER_H

#include <QtGui>

class Logger : public QWidget
{
    Q_OBJECT
public:
    explicit Logger(QWidget *parent = 0);

    ~Logger();
    int number;
    QLabel num;
    QToolButton * button;
    bool checked;

signals:

public slots:

    void setNumber(int number);
    void createButtons();
};

#endif // LOGGER_H

ロガー.cpp

#include "logger.h"
#include <QtGui>

Logger::Logger(QWidget *parent) :
    QWidget(parent)
{
    button = new QToolButton;
    button->setCheckable(true);
    button->setMinimumSize(317,60);
    button->setStyleSheet("QToolButton{background-image: url(images/btn_bg); border:none}");
}

Logger::~Logger()
{
}

void Logger::setNumber(int logNumber)
{
    number=logNumber;
}

void Logger::createButtons()
{
    QLayout * layout = new QHBoxLayout;

    QSpacerItem *spacer = new QSpacerItem(120, 31, QSizePolicy::Maximum, SizePolicy::Maximum);

    num.setStyleSheet("color: white; font: bold 16px");
    num.setText(QString::number(number));

    layout->addWidget(&num);
    layout->addItem(spacer);

    button->setLayout(layout);
}
4

3 に答える 3

6

あなたが達成しようとしていることについて完全には確信が持てません...しかし、あなたの問題は次の2行にあります:

viewport.setLayout(&scrollLayout);
viewport.resize(0,0);

QWidget クラスのドキュメントには、次のように記載されています。

このウィジェットに既にレイアウト マネージャーがインストールされている場合、QWidget は別のインストールを許可しません。新しいレイアウトで setLayout() を呼び出す前に、まず既存のレイアウト マネージャー (layout() によって返される) を削除する必要があります。

ここに問題があります。信じられないかもしれませんが、コードの 2 行の前にこのチェックを追加してください。

 if(layout()){
        qDebug() << "Another layout exists";
    }

出典: QVBoxLayout クラス リファレンス

QVBoxLayout クラスは、ウィジェットを縦に並べます。

このクラスは、垂直ボックス レイアウト オブジェクトを構築するために使用されます。詳細については、QBoxLayout を参照してください。

クラスの最も単純な使用法は次のとおりです。

 QWidget *window = new QWidget;
 QPushButton *button1 = new QPushButton("One");
 QPushButton *button2 = new QPushButton("Two");
 QPushButton *button3 = new QPushButton("Three");
 QPushButton *button4 = new QPushButton("Four");
 QPushButton *button5 = new QPushButton("Five");

 QVBoxLayout *layout = new QVBoxLayout;
 layout->addWidget(button1);
 layout->addWidget(button2);
 layout->addWidget(button3);
 layout->addWidget(button4);
 layout->addWidget(button5);

 window->setLayout(layout);
 window->show();

まず、レイアウトに必要なウィジェットを作成します。次に、QVBoxLayout オブジェクトを作成し、ウィジェットをレイアウトに追加します。最後に、QWidget::setLayout() を呼び出して、QVBoxLayout オブジェクトをウィジェットにインストールします。その時点で、レイアウト内のウィジェットの親が変更され、ウィンドウが親になります。


プロジェクトのエラーの重大な原因:

ウィジェットは、親が削除されると自動的に削除されるため、ヒープ上に構築する必要があります。 ヒープ上でインスタンス化するカスタム ウィジェット クラスがあります。メンバーもヒープに移動する必要があります。また、GUI コードで親/子階層を使用して、適切なメモリ管理と適切な削除を行うことを検討する必要があります。

于 2012-10-01T18:40:01.820 に答える
1

私の経験では、プログラムが停止したRtlFreeHeap場合は、メモリが破損しているという良い兆候です。

通話時

import_btn.setParent(ui->centralWidget);

centralWidgetの所有権を取得しimport_btnます。つまり、centralWidgetが削除されると (これはのデストラクタの一部として発生delete ui;します)、メンバー変数が呼び出されます!MainWindowdelete

これにより、報告されたメモリ破損が発生します。

QPushButtonプレーンなメンバー変数としてではなく、動的に割り当てる必要があります。だからそれらを作るQPushButton*

于 2012-10-02T10:24:54.600 に答える
0

これがmainwindow.cppからの方法です。この質問のおかげで、qtで正しい終了ボタンを作成する方法

QPushButton * quit_btn = new QPushButton(this);
quit_btn->setGeometry(540,440,93,27);
quit_btn->setText("Exit");
QObject::connect(quit_btn,SIGNAL(clicked()),qApp,SLOT(quit()));

完璧に動作します:D

于 2014-03-14T09:35:32.107 に答える