2017-02-20 14 views
0

Я реализовал пример (глава 2) из ​​«Mastering Qt 5» книги, но код аварии при добавлении виджета на макете centralWidget в:SIGSEGV при добавлении виджета в Qt

ui->centralWidget->layout()->addWidget(&mCpuWidget) 

Я подозреваю, что centralWidget не имеет раскладку , поэтому он падает, но я не знаю, как это исправить?

MainWindow::MainWindow(QWidget *parent) : 
QMainWindow(parent), 
ui(new Ui::MainWindow), 
mCpuWidget(this) 
{ 
    ui->setupUi(this); 
    SysInfo::instance().init(); 
    ui->centralWidget->layout()->addWidget(&mCpuWidget); 

} 

Вот еще два класса, которые могут помочь решить проблему. Некоторые из вас могут иметь книгу со всем кодом (следовательно, я упомянул об этом).

CpuWidget::CpuWidget(QWidget* parent): 
SysInfoWidget(parent), 
mSeries (new QPieSeries (this)) 
{ 
    mSeries->setHoleSize(0.35); 
    mSeries->append("CPU Load", 30.0); 
    mSeries->append("CPU Free", 70.0); 

    QChart* chart = chartView().chart(); 
    chart->addSeries(mSeries); 
    chart->setTitle("CPU Average Load"); 
} 

Этот класс создает и устанавливает макет (QVBoxLayout)

SysInfoWidget::SysInfoWidget(QWidget *parent, int startDelayMs, int updateSeriesDelayMs) : 
    QWidget(parent), 
    mChartView(this) 

{ 
    mRefreshTimer.setInterval(updateSeriesDelayMs); 
    connect(&mRefreshTimer, &QTimer::timeout, 
      this, &SysInfoWidget::updateSeries); 

    QTimer::singleShot(startDelayMs, 
         [this] {mRefreshTimer.start();}); 

    mChartView.setRenderHint(QPainter::Antialiasing); 
    mChartView.chart()->legend()->setVisible(false); 

    QVBoxLayout* layout = new QVBoxLayout(this); 
    layout->addWidget(&mChartView); 
    setLayout(layout); 
} 
+0

Попробуйте и посмотрите вывод для 'qDebug() << ui-> centralWidget' и для' qDebug() << ui-> centralWidget-> layout() 'перед линией сбоя. И вообще, за исключением, может быть, главного окна, не является хорошей практикой размещать виджеты пользовательского интерфейса в стеке или как элемент, не являющийся указателем в классе. Он изменяет их жизненный цикл не так, как обычно имеет дело Qt. Вы должны рассмотреть возможность размещения виджета с помощью 'new MyWidget (this)' или 'new MyWidget (someParent)'. Таким образом, это больше похоже на Qt. – AlexanderVX

+0

@AlexanderVX Нет ничего неправильного, чтобы выделить виджет в стеке как член класса. Это действительно зависит от сценария - вам нужно динамически удалять виджет в какой-то момент до того, как деструктор класса виджета станет членом уничтоженного. До тех пор, пока вы не забудете НЕ называть 'delete' на этом виджете, а также передать его в качестве аргумента для различных функций, используя' & '(например:' connect (& this-> myWidgetOnStack, SIGNAL (...), ...) '), вам хорошо идти. – rbaleksandar

+0

@rbaleksandar Это был не главный момент, но сценарии при распределении на стеке не очень хорошие. Например, обновите виджет. И родитель работает в обоих направлениях как экземпляр для выпуска этого дочернего виджета, а также контролирует поведение до степени. Я бы не рекомендовал новичку использовать виджеты в стеке или по значению в классе, хотя он управляемый. – AlexanderVX

ответ

0

Если я не пропустил что-то в коде, которую вы предоставили вы на самом деле не установить центральный виджет. По умолчанию вызов QMainWindow::centralWidget() возвращает указатель NULL. Прежде чем позвонить, вы должны сначала позвонить по номеру QMainWindow::setCentralWidget(QWidget* yourCentralWidget). И да, вам также нужно добавить макет, если вы хотите использовать layout()->addWidget(...). Вы можете создать экземпляр общего QWidget, установить его макет, установить центральный виджет, а затем работать с ним.

+0

Вот что я попросил автора убедиться. – AlexanderVX

0

Вы можете исправить вашу проблему либо путем добавления макета в C++:

ui->setupUi(this); 
SysInfo::instance().init(); 
ui->centralWidget->setLayout(new QVBoxLayout()); // Or any other layout class 
ui->centralWidget->layout()->addWidget(&mCpuWidget); 

Или в Designer UI с помощью этих кнопок: Layout buttons

Обратите внимание, что для кнопок, чтобы быть активным вам нужно иметь по крайней мере 1 виджет в вашем центральном виджете, а затем выбрать свой центральный виджет. Вы можете написать:

ui->setupUi(this); 
SysInfo::instance().init(); 
// One way 
ui->centralWidget->layout()->addWidget(&mCpuWidget); 
// Another way 
ui->layout->addWidget(&mCpuWidget); 

Наконец, вы можете также переместить CpuWidget в файл пользовательского интерфейса с помощью опции «Содействие в ...» в контекстном меню. В этом случае вам не понадобится mCpuWidget, но вы можете получить к нему доступ, используя что-то вроде ui->cpuWidget.

Для получения дополнительной информации прочитайте руководство дизайнера Qt:

+0

Благодарим вас за отзыв. Я потрачу свое время и перевариваю все это. На данный момент я добавил ui-> centralWidget-> setLayout (новый QVBoxLayout()); и он исправил проблему. Я попытался сделать исправление в дизайнере пользовательского интерфейса, но я, должно быть, сделал что-то неправильно, так как не мог заставить его работать. Я был смущен тем, что сделано в классе SysInfoWidget (настройка макета с помощью QVBoxLayout). Хотя это должно было быть сделано в MainWindow, но я предполагаю, что макет применяется только к SysInfoWidget. Мне все еще нужен другой в MainWindow. – Mira

1

Я соавтор книги "Mastering Qt 5"!

Я думаю, ваше подозрение о расположении правильно:

ui->centralWidget->layout()->addWidget(&mCpuWidget); 

Без макета определяется возвращенный деталь нуль так что вы не можете назвать раскладку() метод.

Если у вас есть какая-то ошибка во время обучения вы должны обратиться к заключительному исходному коду, размещенному на GitHub здесь: https://github.com/PacktPublishing/Mastering-Qt-5

Посмотрите на файл «Mastering-Qt-5/Chapter_02/MainWindow.ui»:

<ui version="4.0"> 
    ... 
    <widget class="QWidget" name="centralWidget"> 
    <layout class="QHBoxLayout" name="horizontalLayout"/> 
    </widget> 
... 
</ui> 

, как вы можно увидеть для этого проекта, horizontalLayout типа QHBoxLayout определен в centralWidget. Вы можете легко редактировать файл «.ui» с помощью текстового редактора из Qt Creator со следующими шагами:

  1. правой кнопкой мыши на „mainwindow.ui“ в представлении иерархии проекта
  2. Выберите «Open-With "
  3. Наконец„Обычный текстовый редактор“

Выберите„редактор форм“, когда вы хотите, чтобы вернуться в редактор WYSIWYG.

Как указывается в других ответах, способ сделать это из C++ с помощью следующей строки тоже верно:

ui->centralWidget->setLayout(new QHBoxLayout()); 

Благодарим Вас за выделение отсутствие информации о расположении здесь. Я создал issue, чтобы добавить ошибки об этой теме.