2011-08-17 5 views
2
insérer

(en utilisant Qt 4.6.3, x64, Linux)question QGridLayout avec des widgets

Je teste comment insérer correctement les widgets dans un existant un QGridLayout rempli de divers widgets. Une panne cas est le suivant artificiel:

QApplication app(argc,argv); 
QWidget  w; 
QGridLayout* gl  = new QGridLayout(&w); 
QLabel*  label = new QLabel("Image Size:"); 
QLineEdit* wedit = new QLineEdit("100"); 
QLabel*  xlabel = new QLabel("x"); 

wedit->setAlignment(Qt::AlignRight); 
gl->addWidget(label); 
gl->addWidget(xlabel, 0, 1, 1, 1); 
gl->addWidget(wedit, 0, gl->columnCount()); 

Ce qui crée le widget ci-dessous:

Valid XHTML.

En supposant que ont un existant QGridLayout comme ci-dessus, mais sans l'étiquette « x », et je souhaite insérer cela dans la mise en page, la commutation des deux dernières lignes de addWidget peut sembler valable, à savoir:

\\ same as above 
gl->addWidget(label); 
gl->addWidget(wedit, 0, gl->columnCount()); 
gl->addWidget(xlabel, 0, 1, 1, 1); 

cependant, cela crée les éléments suivants:

Valid XHTML

le gl->columnCount() après est encore 2, à la fois comme x-étiquette et le QLineEdit remplissent la même cellule. Sur la base de cette connaissance, le code suivant produit le résultat souhaité initial:

gl->addWidget(label); 
gl->addWidget(wedit, 0, 2); // note: specified column 2, columnCount() is now 3 
gl->addWidget(xlabel, 0, 1, 1, 1); 

Bien que ce ne soit pas particulièrement utile, car la mise en page originale en question ne se construit pas avec des configurations plus tard à l'esprit.

Puisque addWidget permet de spécifier la position de la cellule, ainsi que l'étendue de la ligne/colonne, il semble étrange que Qt ne remplace pas automatiquement les widgets existants dans la mise en page. Quelqu'un at-il une suggestion sur la façon dont je pourrais surmonter cela? Je suppose qu'il serait possible de recréer un QGridLayout et de copier dedans les enfants de l'original, en prenant soin d'insérer le widget supplémentaire au bon endroit. Ceci est cependant moche, et sensible aux problèmes de version Qt (comme je veux modifier un widget intégré).

Modifier:

Je me rends compte que je fais l'hypothèse de penser à une façon QHBoxLayout, où l'insertion d'un widget est unique compris, alors que dans un QGridLayout ce n'est pas le cas (?).

Je peux préciser que je voudrais finalement modifier QFileDialog::getSaveFileName, en insérant un widget (similaire au widget montré ci-dessus) juste au-dessus des deux rangées inférieures (c'est-à-dire ci-dessus "File & Name:").

Merci

+0

S'il y a un moyen de changer la ligne et la colonne des widgets enfants dans le QGridLayout, il pourrait être possible pour faire une fonction qui prend dans un rowIndex, puis décale la ligne de chaque widget enfant dans row rowIndex et supérieur (à savoir plus bas). – swalog

+0

'QFileDialog :: *', je crois, utiliser les boîtes de dialogue de fichier natif si disponible. Donc, je ne pense pas que vous êtes en mesure de modifier leur mise en page en utilisant Qt. – RedX

+0

J'ai effectivement trouvé une solution à mon problème, donc je crois que c'est possible. J'ai toujours des problèmes mineurs avec le widget enfant ciblé initial. Je posterai une solution quand j'aurai réglé les bizarreries et que je l'ai rendu présentable pour examen. – swalog

Répondre

0

Une solution possible consiste à ajouter de nouveau les widgets qui doivent être déplacés. C'est à dire.

QLayoutItem* x01 = gl->itemAtPosition(0,1); 
gl->addWidget(x01->widget(), 0, 2); 
gl->addWidget(xlabel, 0, 1, 1, 1); 

Maintenant, ce n'est pas particulièrement jolie, ou facile à entretenir, comme une nouvelle version de Qt peut changer le widget d'origine, et aveuglément et le déplacement des enfants cueillette à la main n'est pas intelligent. L'exemple réel suivant (celui que je voulais vraiment résoudre) était de modifier la fenêtre de dialogue "Enregistrer sous" de Qt, qui apparaît en utilisant QFileDialog :: getSaveFileName.

class ImageFileDialog : public QFileDialog { 
public: 
    ImageFileDialog(QWidget* parent); 
    ~ImageFileDialog(); 
    QString getFileName() const; 
    QSize getImageSize() const; 
    QDialog::DialogCode exec(); // Overriden 

protected: 
    void showEvent(QShowEvent* event); // Overriden 

private: 
    QString fileName_; 
    QSize  imageSize_; 
    QLineEdit* widthLineEdit_; 
    QLineEdit* heightLineEdit_; 
}; 

Et dans la source (montrant juste constructeur, la gestion du focus et exec):

ImageFileDialog::ImageFileDialog(QWidget* parent) 
    : fileName_(""), 
    imageSize_(0,0), 
    widthLineEdit_(0), 
    heightLineEdit_(0) 
{ 
    setAcceptMode(QFileDialog::AcceptSave); 
    setFileMode(QFileDialog::AnyFile); 
    setConfirmOverwrite(true); 

    QGridLayout* mainLayout = dynamic_cast<QGridLayout*>(layout()); 
    assert(mainLayout->columnCount() == 3); 
    assert(mainLayout->rowCount() == 4); 

    QWidget*  container  = new QWidget(); 
    QGridLayout* glayout  = new QGridLayout(); 
    QLabel*  imageSizeLabel = new QLabel("Image Size:"); 
    widthLineEdit_    = new QLineEdit("400"); 
    heightLineEdit_    = new QLineEdit("300"); 
    widthLineEdit_->setAlignment(Qt::AlignRight); 
    heightLineEdit_->setAlignment(Qt::AlignRight); 

    container->setLayout(glayout); 
    glayout->setAlignment(Qt::AlignLeft); 
    glayout->addWidget(widthLineEdit_); 
    glayout->addWidget(new QLabel("x"), 0, 1); 
    glayout->addWidget(heightLineEdit_, 0, 2); 
    glayout->addWidget(new QLabel("[pixels]"), 0, 3); 
    glayout->addItem(new QSpacerItem(250, 0), 0, 4); 
    glayout->setContentsMargins(0,0,0,0); // Removes unwanted spacing 

    // Shifting relevant child widgets one row down. 
    int rowCount = mainLayout->rowCount(); 
    QLayoutItem* x00 = mainLayout->itemAtPosition(mainLayout->rowCount()-2,0); 
    QLayoutItem* x10 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,0); 
    QLayoutItem* x01 = mainLayout->itemAtPosition(mainLayout->rowCount()-2,1); 
    QLayoutItem* x11 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,1); 
    QLayoutItem* x02 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,2); 
    assert(x00); assert(x01); assert(x10); assert(x11); assert(x02); 

    mainLayout->addWidget(x00->widget(), rowCount-1, 0, 1, 1); 
    mainLayout->addWidget(x10->widget(), rowCount, 0, 1, 1); 
    mainLayout->addWidget(x01->widget(), rowCount-1, 1, 1, 1); 
    mainLayout->addWidget(x11->widget(), rowCount, 1, 1, 1); 
    mainLayout->addWidget(x02->widget(), rowCount-1, 2, 2, 1); 

    // Adding the widgets in the now empty row. 
    rowCount  = mainLayout->rowCount(); 
    mainLayout->addWidget(imageSizeLabel, rowCount-3, 0, 1, 1); 
    mainLayout->addWidget(container,  rowCount-3, 1, 1, 1); 

    // Setting the proper tab-order 
    QLayoutItem* tmp = mainLayout->itemAtPosition(mainLayout->rowCount()-2,1); 
    QLayoutItem* tmp2 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,1); 
    assert(tmp); assert(tmp2); 
    QWidget::setTabOrder(heightLineEdit_  , tmp->widget()); 
    QWidget::setTabOrder(tmp->widget(), tmp2->widget()); 
} 

// Makes sure the right widget is in focus 
void ImageFileDialog::showEvent(QShowEvent* event) 
{ 
    widthLineEdit_->setFocus(Qt::OtherFocusReason); 
} 

// Called to create the widget 
QDialog::DialogCode ImageFileDialog::exec() 
{ 
    if (QFileDialog::exec() == QDialog::Rejected) 
    return QDialog::Rejected; 
    // The code that processes the widget form and stores results for later calls to 
    // getImageSize() 
    return QDialog:Accepted; 
} 

qui, en utilisant par exemple

ImageFileDialog* dialog = new ImageFileDialog(&w); 
dialog->exec(); 

Crée le widget ci-dessous:

Valid XHTML


Commentaires et façons de le faire mieux, ou pourquoi il en est tout simplement faux sont les bienvenus :)

1

Commutation des deux dernières addWidget lignes ne sont pas valides. Pour le code suivant:

gl->addWidget(label); 
gl->addWidget(wedit, 0, gl->columnCount()); 
gl->addWidget(xlabel, 0, 1, 1, 1); 

Les arguments pour les appels addWidget() sont évalués avant d'ajouter le widget. Par conséquent, gl->columnCount() évalue à un au lieu de deux pour le deuxième appel, puisque la colonne doit encore être créée. Vous ajoutez effectivement deux widgets à la première colonne.

+0

L'exemple que j'ai donné était un cas artificiel, et quelque peu irréaliste. Placer les widgets dans la cellule avant la main n'est pas une option. Je m'excuse si cela n'a pas été rendu plus clair dans mon message. Ce que je voulais faire était d'insérer un widget dans une cellule d'un QGridLayout déjà existant (et non créé par moi). Cela nécessiterait de réaffecter les widgets enfants affectés dans QGridLayout. – swalog

+0

Modifier: relocaliser, pas réaffecter. – swalog

Questions connexes