Greetings all,
Is there any widget to separate two QWidgets and also give full focus to a one widget.
As shown in following figure ?
Thanks in advance,
umanga
How about QSplitter?
QWidget 1, for exmaple, QListView. QWidget 2 is a combination of QWidgets (the left part is simple QPushButton with show/hide caption, and the right part another widget)... All you have to do, is to hide your QWidget2 when user clicked on QPushButton...
If you need an example, I may post it.
Updated
main.cpp
#include "splitter.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
splitter w;
w.show();
return a.exec();
}
splitter.h
#ifndef SPLITTER_H
#define SPLITTER_H
#include <QtGui/QDialog>
class splitter : public QDialog
{
Q_OBJECT;
QWidget* widget1;
QWidget* widget2;
QPushButton* button;
public:
splitter(QWidget *parent = 0, Qt::WFlags flags = 0);
~splitter();
private slots:
void showHide(void);
};
#endif // SPLITTER_H
splitter.cpp
#include <QtGui>
#include "splitter.h"
splitter::splitter(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
QApplication::setStyle("plastique");
QListView* listView = new QListView;
QTableView* tableView = new QTableView;
button = new QPushButton("Hide >");
widget1 = new QWidget;
QHBoxLayout* w1Layout = new QHBoxLayout;
w1Layout->addWidget(listView);
w1Layout->addWidget(button);
widget1->setLayout(w1Layout);
widget2 = new QWidget;
QHBoxLayout* w2Layout = new QHBoxLayout;
w2Layout->addWidget(tableView);
widget2->setLayout(w2Layout);
QSplitter *mainSplitter = new QSplitter(this);
mainSplitter->addWidget(widget1);
mainSplitter->addWidget(widget2);
connect(button, SIGNAL(clicked()), this, SLOT(showHide()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(mainSplitter);
setLayout(mainLayout);
}
splitter::~splitter()
{}
void splitter::showHide(void)
{
if (widget2->isVisible())
{ // hide
widget2->setVisible(false);
button->setText("< Show");
}
else
{ // show
widget2->setVisible(true);
button->setText("Hide >");
}
}
Related
I have a QQuickwidget in a Qt C++ application where i have loaded a QML file (main.qml) and using QAction(actionstart) and C++ functions i have to load another QML file(main1.qml) slightly different to previous one on the same QQuickWidget object.
I am able to do this , but my 2nd QML file is overlapped from the middle section of QQuickwidget and further.
I have did this to stop overlapping of 2 QML files but not successful completely. count3 = 1 is defined in public section of Guiapplication.h file.
void GuiApplication::on_actionstart_triggered()
{
if (count3 == 1)
{
set_animation();
count3 = 2;
}
}
C++ Function for loading 1st QML file(main.qml)
void GuiApplication::rolling_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *contain = QWidget::createWindowContainer(quickWidget,this);
contain->setMinimumSize(1008,349);
contain->setMaximumSize(1008,349);
contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main.qml"));
ui->horizontalLayout_6->addWidget(contain);
}
C++ Function for loading 2nd QML file(main1.qml)
void GuiApplication::set_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *Contain = QWidget::createWindowContainer(quickWidget,this);
Contain->setMinimumSize(1008,349);
Contain->setMaximumSize(1008,349);
Contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main1.qml"));
ui->horizontalLayout_6->addWidget(Contain);
//ui->horizontalLayout_9->invalidate();
//ui->horizontalLayout_9->removeWidget(quickWidget_4);
}
output window image
Depending on whether you want to save or not the state of the QML that you want to hide there are the following alternatives:
Reject the same QQuickWidget (I recommend changing QQuickView to QQuickWidget) and just change the source.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_widget(new QQuickWidget)
{
m_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_widget->setSource(QUrl("qrc:/main1.qml"));
}
void show2(){
m_widget->setSource(QUrl("qrc:/main2.qml"));
}
private:
QQuickWidget *m_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
Use 2 QuickWidgets and use a QStackedWidget to toggle the widgets, with this method only hidden so the state of the QML will persist, in the previous case when changing the source is lost.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_stacked_widget(new QStackedWidget)
{
for(const QString & url: {"qrc:/main1.qml", "qrc:/main2.qml"}){
QQuickWidget *widget = new QQuickWidget;
widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget->setSource(QUrl(url));
m_stacked_widget->addWidget(widget);
}
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_stacked_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_stacked_widget->setCurrentIndex(0);
}
void show2(){
m_stacked_widget->setCurrentIndex(1);
}
private:
QStackedWidget *m_stacked_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
The examples can be found here
I'm looking to do something like the following:
example
But with radio buttons instead of checkboxes. In the above picture widgets are placed into groups which can be enabled/disabled, but I want only 1 group to be enabled at a time (in the example both Group A and Group C are enabled).
I did the above example using QGroupBox, but it only provides normal checkboxes, not radio buttons as far as I can tell.
The ckeckbox that appears in the QGroupBox is not a QCheckBox, it is just a drawing. So a possible solution is to create a class that manages the QGroupBox checked.
#include <QApplication>
#include <QGroupBox>
#include <QLineEdit>
#include <QRadioButton>
#include <QSlider>
#include <QVBoxLayout>
class ExclusiveManager: public QObject{
public:
using QObject::QObject;
void addGroupBox(QGroupBox *groupbox){
if(groupbox){
groupbox->blockSignals(true);
groupbox->setChecked(m_groupboxs.isEmpty());
groupbox->blockSignals(false);
m_groupboxs << groupbox;
connect(groupbox, &QGroupBox::toggled, this, &ExclusiveManager::onToggled);
}
}
private slots:
void onToggled(bool on){
QGroupBox *groupbox = qobject_cast<QGroupBox *>(sender());
if(on){
for(QGroupBox *g: m_groupboxs){
if(g != groupbox && g->isChecked()){
g->blockSignals(true);
g->setChecked(false);
g->blockSignals(false);
}
}
}
else{
groupbox->blockSignals(true);
groupbox->setChecked(false);
groupbox->blockSignals(false);
}
}
private:
QList<QGroupBox *> m_groupboxs;
};
class Widget: public QWidget{
public:
Widget(QWidget *parent=nullptr):QWidget(parent){
setLayout(new QVBoxLayout);
ExclusiveManager *manager = new ExclusiveManager(this);
group_a = new QGroupBox("Group A");
group_a->setCheckable(true);
group_b = new QGroupBox("Group B");
group_b->setCheckable(true);
group_c = new QGroupBox("Group C");
group_c->setCheckable(true);
layout()->addWidget(group_a);
layout()->addWidget(group_b);
layout()->addWidget(group_c);
manager->addGroupBox(group_a);
manager->addGroupBox(group_b);
manager->addGroupBox(group_c);
QVBoxLayout *layA = new QVBoxLayout();
layA->addWidget(new QLineEdit);
group_a->setLayout(layA);
QVBoxLayout *layB = new QVBoxLayout();
layB->addWidget(new QRadioButton("Option 1"));
layB->addWidget(new QRadioButton("Option 2"));
group_b->setLayout(layB);
QVBoxLayout *layC = new QVBoxLayout();
layC->addWidget(new QSlider(Qt::Horizontal));
group_c->setLayout(layC);
}
private:
QGroupBox *group_a;
QGroupBox *group_b;
QGroupBox *group_c;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
You can link each QGroupBox'toggled signal with the other's setDisabled slot.
ps: I know it's too late but I'm just putting it here if someone else needs it.
I am trying to show a QMainWindow inside a QDialog but the former does not appear.
I have subclassed QDialog, let's call it myDialog
A small example:
myDialog(QWidget *p_parent) : QDialog(p_parent)
{
QGridLayout *p_dialogLayout = new QGridLayout(this);
QMainWindow *p_MainWindow = new QMainWindow(this);
QLabel *p_label = new QLabel(this);
p_MainWindow->setCentralWidget(p_label);
QPushButton *p_cancel = new QPushButton("Cancel", this);
p_dialogLayout ->addWidget(p_MainWindow, 0, 0);
p_dialogLayout ->addWidget(p_cancel, 1, 0);
}
If I execute the dialog, I only see the button, not the embeded QMainWindow.
If i force to show the qmainwindow, the mainwindow is shown in another window.
Use QLayout::setMenuBar to add a toolbar to your dialog.
#include <QtWidgets>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr) : QDialog(parent)
{
resize(600, 400);
setLayout(new QHBoxLayout);
QToolBar *toolbar = new QToolBar;
toolbar->addAction("Action one");
toolbar->addAction("Action two");
layout()->setMenuBar(toolbar);
layout()->addWidget(new QLabel("Label one"));
layout()->addWidget(new QLabel("Label two"));
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
#include "main.moc"
I don't think this is supported by the Qt framework, according to their documentation from here, it's intended to be used only once in an application.
My suggestion would be to take all your MainWindow implementation in a separate form (inheriting QWidget), and just add that form to your MainWindow in the constructor using something like p_MainWindow->setCentralWidget(p_YourNewForm);
I have been able to do it.
The trick is to construct the QMainWindow without a parent, and then apply the .setParent
Here is how:
myDialog(QWidget *p_parent) : QDialog(p_parent)
{
QGridLayout *p_dialogLayout = new QGridLayout(this);
QMainWindow *p_MainWindow = new QMainWindow(); //Without a parent
QLabel *p_label = new QLabel(this);
p_MainWindow->setCentralWidget(p_label);
QPushButton *p_cancel = new QPushButton("Cancel", this);
p_dialogLayout ->addWidget(p_MainWindow, 0, 0);
p_dialogLayout ->addWidget(p_cancel, 1, 0);
p_MainWindow->setParent(this); //Set the parent, to delete the MainWindow when the dialog is deleted.
}
I have a custom widget with some standard child widgets inside. If I make a separate test project and redefine my custom widget to inherit QMainWindow, everything is fine. However, if my custom widget inherits QWidget, the window opens, but there are no child widgets inside.
This is the code:
controls.h:
#include <QtGui>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
class Controls : public QWidget
{
Q_OBJECT
public:
Controls();
private slots:
void render();
private:
QWidget *frame;
QWidget *renderFrame;
QVBoxLayout *layout;
QLineEdit *rayleigh;
QLineEdit *mie;
QLineEdit *angle;
QPushButton *renderButton;
};
controls.cpp:
#include "controls.h"
Controls::Controls()
{
frame = new QWidget;
layout = new QVBoxLayout(frame);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
frame->setLayout(layout);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
main.cpp:
#include <QApplication>
#include "controls.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Controls *controls = new Controls();
controls->show();
return app.exec();
}
This opens up a window with correct dimensions, but with no content inside.
Bear in mind this is my first day using Qt. I need to make this work without inheriting QMainWindow because later on I need to put this on a QMainWindow.
You're missing a top level layout:
Controls::Controls()
{
... (yoour code)
QVBoxLayout* topLevel = new QVBoxLayout(this);
topLevel->addWidget( frame );
}
Or, if frame is not used anywhere else, directly:
Controls::Controls()
{
layout = new QVBoxLayout(this);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
Note that setLayout is done automatically when QLayout is created (using parent widget)
You'll want to set a layout on your Controls class for managing its child sizes. I'd recommend removing your frame widget.
controls.cpp
Controls::Controls()
{
layout = new QVBoxLayout(this);
.
.
.
}
main.cpp
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
I have the following minimal example code given.
main.cpp:
#include <QApplication>
#include "qt.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyDialog mainWin;
mainWin.show();
return app.exec();
}
qt.cpp:
#include <QLabel>
#include "qt.h"
void MyDialog::setupUi()
{
setCentralWidget(new QWidget);
mainLayout = new QVBoxLayout( centralWidget() );
centralWidget()->setLayout(mainLayout);
// show the add new effect channel button
QPushButton* newKnobBtn = new QPushButton("new", this );
connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );
containerWidget = new QWidget(this);
scrollArea = new QScrollArea(containerWidget);
mainLayout->addWidget(containerWidget);
scrollLayout = new QVBoxLayout(scrollArea);
scrollArea->setLayout(scrollLayout);
/*
QSizePolicy pol;
pol.setVerticalPolicy(QSizePolicy::Expanding);
setSizePolicy(pol);
*/
addNewKnob(); // to fit size initially
}
void MyDialog::addNewKnob()
{
scrollLayout->addWidget(new QLabel("Hello World", this));
/*
containerWidget->adjustSize();
adjustSize();
*/
}
qt.h:
#include <QMainWindow>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QPushButton>
class MyDialog : public QMainWindow
{
Q_OBJECT
private slots:
void addNewKnob();
private:
void setupUi();
QVBoxLayout* mainLayout;
QScrollArea* scrollArea;
QVBoxLayout* scrollLayout;
QWidget* containerWidget;
public:
MyDialog( ) { setupUi(); }
};
Compiling: Put all in one directory, type
qmake -project && qmake && make
I have the adjustSize() solution from here, but it does not work: (link). Everything I commented out was things I tried but did not help.
How do I make containerWidget and scrollLayout grow correctly, when a new Label is being added to scrollLayout?
Here's a simplified version that works for me:
qt.cpp:
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include "qt.h"
MyDialog::MyDialog()
{
QWidget * mainWidget = new QWidget;
QBoxLayout * mainLayout = new QVBoxLayout(mainWidget);
setCentralWidget(mainWidget);
// show the add new effect channel button
QPushButton* newKnobBtn = new QPushButton("new");
connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );
QScrollArea * scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
mainLayout->addWidget(scrollArea);
QWidget * labelsWidget = new QWidget;
labelsLayout = new QVBoxLayout(labelsWidget);
scrollArea->setWidget(labelsWidget);
addNewKnob(); // to fit size initially
}
void MyDialog::addNewKnob()
{
labelsLayout->addWidget(new QLabel("Hello World"));
}
qt.h:
#include <QMainWindow>
#include <QBoxLayout>
class MyDialog : public QMainWindow
{
Q_OBJECT
public:
MyDialog( );
private slots:
void addNewKnob();
private:
QBoxLayout * labelsLayout;
};
You have containerWidget that contain only one QScrollArea. I don't know why do you need this. But if you need this for some reason, you need to add a layout to this widget in order to make layouts work. Also do not create a layout for QScrollArea. It already have internally implemented layout. You should add scrollLayout to the scroll area's viewport() widget instead.
When you construct a layout and pass a widget to its constructor, the layout is automatically assigned to the passed widget. You should not call setLayout after that. This action will take no effect and produce console warning.