Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Qt, C++] Dynamiczne tworzenie przycisków i wstawianie ich do layoutu

Ostatnio zmodyfikowano 2015-01-02 16:46
Autor Wiadomość
kitsss
Temat założony przez niniejszego użytkownika
[Qt, C++] Dynamiczne tworzenie przycisków i wstawianie ich do layoutu
» 2014-12-28 17:21:30
Dopiero zaczynam przygodę z QT więc proszę o wyrozumiałość.
Zadanie polega na tym, że mamy wybrać sobie widgetem QComboBox ilość przycisków do rysowania w czasie rzeczywistym.
Niestety brak oczekiwanego efektu.

Plik .h
C/C++
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QApplication>
#include <QPushButton>
#include <QString>
#include <QComboBox>


namespace Ui {
    class MainWindow;
}

class MainWindow
    : public QMainWindow
{
    QComboBox * QCB;
    QPushButton * QPB_table[ 9 ];
    int Amount;
   
    Q_OBJECT
   
private slots:
    void Delete_Buttons();
   
public:
    explicit MainWindow( QWidget * parent = 0 );
    ~MainWindow();
   
private:
    Ui::MainWindow * ui;
    void Draw_Buttons();
    void Add_QComboBox();
};

#endif // MAINWINDOW_H

Plik .cpp
C/C++
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow( QWidget * parent )
    : QMainWindow( parent )
     , ui( new Ui::MainWindow )
{
    ui->setupUi( this );
    setMinimumSize( 750, 500 );
    setMaximumSize( 1750, 1500 );
    setGeometry( 300, 200, 1000, 700 );
    Add_QComboBox();
   
   
   
    QString x = QCB->currentText();
    Amount = x.toInt();
   
    connect( QCB, SIGNAL( currentTextChanged( QString ) ), this, SLOT( Delete_Buttons ) );
}

void MainWindow::Add_QComboBox()
{
    QCB = new QComboBox( this );
    QCB->setGeometry( 800, 350, 100, 50 );
    QCB->addItem( "0" );
    QCB->addItem( "1" );
    QCB->addItem( "2" );
    QCB->addItem( "3" );
    QCB->addItem( "4" );
    QCB->addItem( "5" );
    QCB->addItem( "6" );
    QCB->addItem( "7" );
    QCB->addItem( "8" );
    QCB->addItem( "9" );
}

void MainWindow::Draw_Buttons()
{
    QString a = QCB->currentText();
    QString b;
    for( int i = 0, j = 100; i < a.toInt(); i++, j += 100 )
    {
        QPB_table[ i ] = new QPushButton( b = QString( "%1 %2" ).arg( "Przycisk" ).arg( i ), this );
        QPB_table[ i ]->setGeometry( j, 100, 75, 50 );
    }
}

void MainWindow::Delete_Buttons()
{
    for( int i = 0; i < Amount; i++ )
         delete QPB_table[ i ];
   
    Draw_Buttons();
}

MainWindow::~MainWindow()
{
    delete ui;
}
P-123464
turaz
» 2014-12-28 20:25:55
Witaj.
Problemem w Twoim przypadku jest nie umieszczanie widget'ów  w layout.
Jeżeli zastosujesz jakikolwiek layout w centralWiget (który posiada MainWindow) i użyjesz na tym layout'cie metody addWidget() będzie działać :)

Stosowanie layout'ów ma pozytywne skutki przy zmianie rozmiaru okna oraz to, że nie musisz martwić się o wymiary widget'ów, które same zostaną odpowiednio wyskalowane.

PS1. Jestem nowym użytkownikiem na tym forum i dopiero zauważyłem, że znajduje się tutaj w dziale 'Kursy' artykuł o layoutach: http://blog.matthew.org.pl/2009/11/27/kurs-qt-czesc-5-layout/ może coś Ci się rozjaśni.
PS2. Qt != QT :) (taki mały szczegół :P)
P-123496
kitsss
Temat założony przez niniejszego użytkownika
» 2014-12-29 15:39:22
Nie bardzo wiem, czemu tym razem wyrzuca błąd podczas działania programu:
C/C++
MainWindow::MainWindow( QWidget * parent )
    : QMainWindow( parent )
     , ui( new Ui::MainWindow )
{
    ui->setupUi( this );
    setMinimumSize( 750, 500 );
    setMaximumSize( 1750, 1500 );
    setGeometry( 300, 200, 1000, 700 );
    Add_QComboBox();
   
    layout = new QHBoxLayout( this );
   
   
    QString x = QCB->currentText();
    Amount = x.toInt();
   
    connect( QCB, SIGNAL( currentTextChanged( QString ) ), this, SLOT( Delete_Buttons ) );
   
    QWidget * window = new QWidget();
    window->setLayout( layout );
    setCentralWidget( window );
}

void MainWindow::Add_QComboBox()
{
    QCB = new QComboBox( this );
    QCB->setGeometry( 800, 350, 100, 50 );
    QCB->addItem( "0" );
    QCB->addItem( "1" );
    QCB->addItem( "2" );
    QCB->addItem( "3" );
    QCB->addItem( "4" );
    QCB->addItem( "5" );
    QCB->addItem( "6" );
    QCB->addItem( "7" );
    QCB->addItem( "8" );
    QCB->addItem( "9" );
}

void MainWindow::Draw_Buttons()
{
    QString a = QCB->currentText();
    QString b;
    for( int i = 0, j = 100; i < a.toInt(); i++, j += 100 )
    {
        QPB_table[ i ] = new QPushButton( b = QString( "%1 %2" ).arg( "Przycisk" ).arg( i ) );
        layout->addWidget( QPB_table[ i ] );
    }
}

void MainWindow::Delete_Buttons()
{
    for( int i = 0; i < Amount; i++ )
         delete QPB_table[ i ];
   
    Draw_Buttons();
}

MainWindow::~MainWindow()
{
    delete ui;
}
P-123539
turaz
» 2014-12-29 18:01:01
Jeśli używasz QtCreator'a to zobaczysz w nim zakładkę 'Design', która w naprawdę przystępny sposób jest w stanie pomóc w tworzeniu GUI, ale wracając do tematu stworzony QMainWindow posiada już swój cetralWidget (spójrz w zakładkę DESIGN)
zmieniając konstruktor na taki:
C/C++
MainWindow::MainWindow( QWidget * parent )
    : QMainWindow( parent )
     , ui( new Ui::MainWindow )
{
    ui->setupUi( this );
    setMinimumSize( 750, 500 );
    setMaximumSize( 1750, 1500 );
    setGeometry( 300, 200, 1000, 700 );
    Add_QComboBox();
   
    layout = new QHBoxLayout( ui->centralWidget );
    ui->centralWidget->setLayout( layout );
   
    QString x = QCB->currentText();
    Amount = x.toInt();
   
    connect( QCB, SIGNAL( currentTextChanged( QString ) ), this, SLOT( Delete_Buttons() ) );
}
napewno będzie działać :)
PS. Sory ale nei wiem jak sformatować kod źródłowy, żeby był odpowiednio sformatowany.
P-123577
kitsss
Temat założony przez niniejszego użytkownika
» 2014-12-30 14:02:25
Jest ok, wszystko widać. Dzięki wielkie, już działa. Teraz jeszcze muszę rozkminić dlaczego przyciski z layoutu nie są usuwane.
P-123648
turaz
» 2014-12-30 15:07:01
Są usuwane.. z tym, że masz mały błąd, ponieważ w slocie
DeleteButtons()
 pętla jest wykonywana do momentu gdy
i < Amount
 a pole Amount jest ustawiane wyłącznie w konstruktorze gdzie najprawdopodobniej QComboBox ma wartość 0. Swoją drogą na QObject'ach w Qt nei zaleca sie używania
delete
 lecz metody
deleteLater()
 ona również usunie ten obiekt z tym, że nastąpi to razem z event loopem, a nie natychmiast. Plusem takiego działania jest to, że jeżeli w Event loopie występują jeszcze jakieś zdarzenia związane z tym obiektem mogą spowodować Segmentation Fault, a tego byśmy nie chcieli :)
PS. Żeby było przyjemniej ja zamiast tabeli przetrzymującej wskaźniki do QPushbuton'ow użyłbym QList<QPushButton*> (ale to tylko moja taka nic nie znacząca uwaga) :)
P-123655
kitsss
Temat założony przez niniejszego użytkownika
» 2015-01-02 16:25:14
Już rozumiem, trochę poczytałem o tym właśnie, i tym samym ty jeszcze bardziej mi to wyjaśniłeś i potwierdziłes :) Dzięki wielkie!
P-123873
turaz
» 2015-01-02 16:46:59
Polecam się na przyszłość, gdybyś walczył z Qt :)
P-123875
« 1 »
  Strona 1 z 1