A program has the main window, the menu bar, the menu item (QAction in Qt), the tab widget, the text edit. I try to receive the sequenced numeration in the tabs when I press on the menu item (New Tab).
When I press on the New Tab then tab 1, tab 2, tab 3, tab 4 and so on must appear.
The suggested approximate code is here:
MainWindow::MainWindow(QWidget* parent):QMainWindow(parent)
{
QMenuBar* menuBar = new QMenuBar(this);
setMenuBar(menuBar);
QMenu* fileMenu = new QMenu("&File", this);
menuBar->addMenu(fileMenu);
QAction* newTabAction = new QAction("&New Tab", this);
fileMenu->addAction(newTabAction);
connect(newTabAction, SIGNAL(triggered()), this, SLOT(newTabActionHandler()));
QTabWidget* tabWidget = new QTabWidget(this);
QList<QWidget*> widgetList;
widgetList.append(new QWidget(this));
tabWidget->addTab(widgetList[0], "Tab 0");
tabWidget->setMovable(true);
tabWidget->setTabsClosable(true);
QList<QTextEdit*> textEditList;
textEditList.append(new QTextEdit(this));
QVBoxLayout* vBoxLayout = new QVBoxLayout();
widgetList[0]->setLayout(vBoxLayout);
vBoxLayout->addWidget(textEditList[0]);
setCentralWidget(tabWidget);
}
void MainWindow::newTabActionHandler()
{
widgetList.append(new QWidget(this));
tabWidget->addTab(widgetList[widgetList.size()-1], ????);
textEditList.append(new QTextEdit(this));
QVBoxLayout* vBoxLayout = new QVBoxLayout();
widgetList[widgetList.size()-1]->setLayout(vBoxLayout);
vBoxLayout->addWidget(textEditList[textEditList.size()-1]);
}
Please, put the correct code into the line where question signs take place to be (in the newTabActionHandler() method body).
tabWidget->addTab(widgetList[widgetList.size()-1], ????);
Thank You!
You have to order your code, in this case you only need to use the size of the list. but I have given the freedom to correct your code, for example widgetList and textEditList are local variables so you can not access from the slot so it is appropriate that they are members of the class.
Another recommendation is to order your code, the more readable your code is, so you can create widget and textedit and make your links without using your containers.
mainwindow.cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void newTabActionHandler();
private:
QList<QWidget*> widgetList;
QList<QTextEdit*> textEditList;
QTabWidget* tabWidget;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QMenu>
#include <QMenuBar>
#include <QTextEdit>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QMenuBar *menuBar = new QMenuBar(this);
setMenuBar(menuBar);
QMenu* fileMenu = new QMenu("&File", this);
menuBar->addMenu(fileMenu);
QAction *newTabAction = new QAction("&New Tab", this);
fileMenu->addAction(newTabAction);
connect(newTabAction, &QAction::triggered, this, &MainWindow::newTabActionHandler);
tabWidget = new QTabWidget(this);
tabWidget->setMovable(true);
tabWidget->setTabsClosable(true);
newTabActionHandler();
setCentralWidget(tabWidget);
}
void MainWindow::newTabActionHandler()
{
QWidget *widget = new QWidget;
widgetList << widget;
tabWidget->addTab(widget, QString("Tab %1").arg(widgetList.size()-1));
QTextEdit *textEdit = new QTextEdit;
textEditList << textEdit;
QVBoxLayout* vBoxLayout = new QVBoxLayout(widget);
vBoxLayout->addWidget(textEdit);
}
MainWindow::~MainWindow()
{
}
You can find the complete example in the following link
Replace ???? by QString("Tab %1").arg(widgetList.size()-1)
Related
I am new to Qt application programming, I have a task to complete i.e
I need to create a paint like application
Based on left side panel objects Right side List must display..
PFA
so now i am stuck with displaying right side panel
To be more clear...
I used left side QGroupBox with Push Buttons.
Right side i used QGridLayout to show specific objects.
Center graphics view ( ignore this point).
now when I am calling the function after push button clicked Button 1 : should display only numbered objects Button 2 : should display only other objects Button 3 : should display empty plane Button N : should display all objects
could some one suggest me with small code for it.... like
ui->gridLayout_1->... ( to hide previous options )
when called second time ui->gridLayout_1->addWidget(label0,0,0); should display relevant
when called for third time display all objects ui->gridLayout_1->addWidget(label0,0,0);
Edit: After seeing a better example of what you were trying to accomplish I threw this together using QStackedWidget. I think the below code mimics the behavior you are looking for. This has replaced my old answer as I didn't want to add any unnecessary confusion.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMainWindow>
#include <QPushButton>
#include <QStackedWidget>
#include <QWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
QWidget *central_widget = new QWidget(this);
QHBoxLayout *central_layout = new QHBoxLayout();
QVBoxLayout *ctl_btn_layout = new QVBoxLayout();
QPushButton *ctl_btn_1 = new QPushButton("1", central_widget);
QPushButton *ctl_btn_2 = new QPushButton("2", central_widget);
QStackedWidget *widget_stack = new QStackedWidget(central_widget);
QWidget *page_0 = new QWidget();
QWidget *page_1 = new QWidget();
QGridLayout *page_1_layout = new QGridLayout();
QPushButton *r_btn = new QPushButton("R", page_1);
QPushButton *j_btn = new QPushButton("J", page_1);
QPushButton *l_btn = new QPushButton("L", page_1);
QPushButton *o_btn = new QPushButton("O", page_1);
QPushButton *v_btn = new QPushButton("V", page_1);
QPushButton *f_btn = new QPushButton("F", page_1);
QWidget *page_2 = new QWidget();
QVBoxLayout *page_2_layout = new QVBoxLayout();
QPushButton *btn_1 = new QPushButton("1", page_2);
QPushButton *btn_2 = new QPushButton("2", page_2);
QPushButton *btn_3 = new QPushButton("3", page_2);
QPushButton *btn_4 = new QPushButton("4", page_2);
QPushButton *btn_5 = new QPushButton("5", page_2);
QPushButton *btn_6 = new QPushButton("6", page_2);
QLabel *r = new QLabel("R", central_widget);
QLabel *j = new QLabel("J", central_widget);
QLabel *id = new QLabel("ID", central_widget);
QLabel *x = new QLabel("X", central_widget);
QLabel *y = new QLabel("Y", central_widget);
QLineEdit *r_line = new QLineEdit(central_widget);
QLineEdit *j_line = new QLineEdit(central_widget);
QLineEdit *id_line = new QLineEdit(central_widget);
QLineEdit *x_line = new QLineEdit(central_widget);
QLineEdit *y_line = new QLineEdit(central_widget);
QVBoxLayout *lines_layout = new QVBoxLayout();
public slots:
void ctl_btn_1_clicked();
void ctl_btn_2_clicked();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ctl_btn_layout->addWidget(ctl_btn_1);
connect(ctl_btn_1, SIGNAL(clicked(bool)), this, SLOT(ctl_btn_1_clicked()));
ctl_btn_layout->addWidget(ctl_btn_2);
connect(ctl_btn_2, SIGNAL(clicked(bool)), this, SLOT(ctl_btn_2_clicked()));
central_layout->addLayout(ctl_btn_layout);
page_1_layout->addWidget(r_btn, 0, 0, 1, 1);
page_1_layout->addWidget(j_btn, 1, 1, 1, 1);
page_1_layout->addWidget(l_btn, 2, 0, 1, 1);
page_1_layout->addWidget(o_btn, 3, 1, 1, 1);
page_1_layout->addWidget(v_btn, 4, 2, 1, 1);
page_1_layout->addWidget(f_btn, 5, 3, 1, 1);
page_1->setLayout(page_1_layout);
page_2_layout->addWidget(btn_1);
page_2_layout->addWidget(btn_2);
page_2_layout->addWidget(btn_3);
page_2_layout->addWidget(btn_4);
page_2_layout->addWidget(btn_5);
page_2_layout->addWidget(btn_6);
page_2->setLayout(page_2_layout);
widget_stack->addWidget(page_0); //Empty QWidget.
widget_stack->addWidget(page_1);
widget_stack->addWidget(page_2);
central_layout->addWidget(widget_stack);
lines_layout->addWidget(r);
r->hide();
lines_layout->addWidget(r_line);
r_line->hide();
lines_layout->addWidget(j);
j->hide();
lines_layout->addWidget(j_line);
j_line->hide();
lines_layout->addWidget(id);
id->hide();
lines_layout->addWidget(id_line);
id_line->hide();
lines_layout->addWidget(x);
x->hide();
lines_layout->addWidget(x_line);
x_line->hide();
lines_layout->addWidget(y);
y->hide();
lines_layout->addWidget(y_line);
y_line->hide();
central_layout->addLayout(lines_layout);
central_widget->setLayout(central_layout);
setCentralWidget(central_widget);
}
MainWindow::~MainWindow()
{
}
void MainWindow::ctl_btn_1_clicked()
{
if (j->isVisible())
{
j->hide();
j_line->hide();
}
r->show();
r_line->show();
if (!id->isVisible())
{
id->show();
id_line->show();
x->show();
x_line->show();
y->show();
y_line->show();
}
widget_stack->setCurrentIndex(1);
}
void MainWindow::ctl_btn_2_clicked()
{
if (r->isVisible())
{
r->hide();
r_line->hide();
}
j->show();
j_line->show();
if (!id->isVisible())
{
id->show();
id_line->show();
x->show();
x_line->show();
y->show();
y_line->show();
}
widget_stack->setCurrentIndex(2);
}
This works by using a QStackedWidget, which is populated with 3 QWidgets. The first widget is completely empty to mimic the empty page from your example. The second and third widgets have layouts that hold your different button configurations, and the QStackedWidget will flip between pages through functions connected to the button slots.
Note that I tend not to use the form designer that comes w/ Qt Creator, preferring pure C++ UI design. It doesn't matter how you set it up, with or without the form, I just find it easier this way. Main.cpp was left as default from a new Qt GUI project with the generate form box unchecked.
iam trying to control an action on C++ of a QMenu in QT Creator. i have a window that has a label posting the action the user clicks from a menu to text but i want to control each sub menu seperately (the action of its).
Different function for "OPEN", different function for "QUIT" etc.
Any ideas?
MainWindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setFixedSize(500,300);
setWindowTitle("Menu Demo");
mainWidget=new QWidget;
setCentralWidget(mainWidget);
mainWidget->setFixedSize(this->width(),this->height());
mainLayout=new QVBoxLayout;
mainWidget->setLayout(mainLayout);
mainLabel=new QLabel;
mainLayout->addWidget(mainLabel);
fileMenu= new QMenu("FILE");
**fileMenu->addAction("SAVE"); //ACTIONS......different function.
**fileMenu->addAction("SAVE AS");**
**fileMenu->addAction("QUIT");****
editMenu= new QMenu("EDIT");
**editMenu->addAction("COPY");**
**editMenu->addAction("CUT");**
**editMenu->addAction("PASTE");**
menuBar()->addMenu(fileMenu);
menuBar()->addMenu(editMenu);
connect(fileMenu,SIGNAL(triggered(QAction*)),this,SLOT(menuSlot(QAction*)));
connect(editMenu,SIGNAL(triggered(QAction*)),this,SLOT(menuSlot(QAction*)));
}
void MainWindow::menuSlot(QAction *action)
{
mainLabel->setText("ACTION: "+action->text());
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
# include <QVBoxLayout>
# include <QHBoxLayout>
# include <QLabel>
# include <QMenu>
# include <QMenuBar>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
private:
QWidget *mainWidget;
QVBoxLayout *mainLayout;
QLabel *mainLabel;
QMenuBar *menubar;
QMenu *fileMenu;
QMenu *editMenu;
public slots:
void menuSlot(QAction *action);
};
#endif // MAINWINDOW_H
Just test action->text() in MainWindow::menuSlot and perform the requested action...
void MainWindow::menuSlot (QAction *action)
{
mainLabel->setText("ACTION: "+action->text());
if (action->text() == "SAVE") {
/*
* Do whatever is required for `SAVE'.
*/
} else if (action->text() == "SAVE AS") {
/*
* Do whatever is required for `SAVE AS'.
*/
}
}
You just need to make sure the text associated with each QAction is unique.
Alternatively, you could have a slot for each action...
fileMenu= new QMenu("FILE");
auto *a = fileMenu->addAction("SAVE");
connect(a, SIGNAL(triggered(QAction *)), this, SLOT(save_slot(QAction *)));
a = fileMenu->addAction("SAVE AS");
connect(a, SIGNAL(triggered(QAction *)), this, SLOT(save_as_slot(QAction *)));
a = fileMenu->addAction("QUIT");
connect(a, SIGNAL(triggered(QAction *)), this, SLOT(quit_slot(QAction *)));
As a side note, if you're using Qt5 you should prefer the new connect syntax for signals and slots.
How do I change the QWidget inside a tab of a QTabWidget, knowing only the tab index?
void MainWindow::on_toolButton_2_clicked()
{
TextItem myitem = new TextItem;//is a class TextItem : public QWidget
int tabindex = 2;
ui->tabwidget1->//i don't have a idea to change widget of a Tab by tab index
}
It's hard to say what solution would best suit your problem since you don't explain much of it.
A first approach would be to wrap the content of each tab inside a container QWidget: when you want to change the content of one tab, you just have to change the content of the container QWidget.
Another approach would be to delete the tab with the old content and create a new one with the new content.
EDIT:
Here is a quick implementation of the first approach I mentioned above:
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void buildTabWidget();
private slots:
void changeTabContent() const;
private:
QTabWidget* tab_widget;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include <QLabel>
#include <QLayout>
#include <QPushButton>
#include <QTabWidget>
void MainWindow::buildTabWidget()
{
// The container will hold the content that can be changed
QWidget *container = new QWidget;
tab_widget = new QTabWidget(this);
tab_widget->addTab(container, "tab");
// The initial content of the container is a blue QLabel
QLabel *blue = new QLabel(container);
blue->setStyleSheet("background: blue");
blue->show();
}
void MainWindow::changeTabContent() const
{
// retrieve the QWidget 'container'
QWidget *container = tab_widget->widget(0);
// the 'blue' QLabel
QWidget *old_content = dynamic_cast<QWidget*>(container->children()[0]);
delete old_content;
// create a red QLabel, as a new content
QWidget *new_content = new QLabel(container);
new_content->setStyleSheet("background: red");
new_content->show();
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
buildTabWidget();
QPushButton* push_button = new QPushButton("Change content");
connect(push_button, SIGNAL(clicked(bool)), this, SLOT(changeTabContent()));
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(tab_widget);
layout->addWidget(push_button);
QWidget *window = new QWidget();
window->setLayout(layout);
window->show();
setCentralWidget(window);
}
Clicking the button Change content will delete the old content (the blue QLabel) in the tab, and will replace it by creating a new content (a red QLabel):
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 >");
}
}
I have a problem with a QGridLayout. One row of my layout contains an element (QProgressbar) that is normaly hidden. When there is some progress to report i call show on it. The problem is that when i call show on the QProgressbar the row above the row containing it will be slightly resized in height (1-3 px). So the whole layout does a little "jump" which looks ugly.
I have given a minimalRowHeight to the row that contains the QProgressbar that is much larger then the height of the QProgressbar but still the height of the row will increase on show().
I have attached a very minimal version of my program that demonstrates the problem. Can anyone give me a hint what is going on there?
Header:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
#include <QLineEdit>
#include <QtWebKit/QWebView>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
private:
QLineEdit* input;
QWebView *webview;
private slots:
void slotLoadButton();
};
#endif // MAINWINDOW_H
Source:
#include "mainwindow.h"
#include <QProgressBar>
#include <QPushButton>
#include <QGridLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QGridLayout *grid = new QGridLayout;
input = new QLineEdit;
QPushButton *loadButton = new QPushButton("load");
connect(loadButton, SIGNAL(clicked()),
this, SLOT(slotLoadButton()));
webview = new QWebView;
QProgressBar *progress = new QProgressBar;
progress->setFixedHeight(25);
progress->hide();
connect(webview, SIGNAL(loadStarted()),
progress, SLOT(show()));
connect(webview, SIGNAL(loadProgress(int)),
progress, SLOT(setValue(int)));
connect(webview, SIGNAL(loadFinished(bool)),
progress, SLOT(hide()));
grid->addWidget(input, 0, 0);
grid->addWidget(loadButton, 0, 1);
grid->addWidget(webview, 1, 0, 1, -1);
grid->setRowMinimumHeight(2, 35);
grid->addWidget(progress, 2, 1);
QWidget* widget = new QWidget;
widget->setLayout(grid);
setCentralWidget(widget);
}
void MainWindow::slotLoadButton()
{
QUrl url = input->text();
webview->load(url);
}
This is likely caused by the vertical spacing and/or margins of the layout. You should try playing with those properties.
This looks like a bug in Qt. Try reporting it
This is a workaround:
//grid->addWidget(progress, 2, 1);
QHBoxLayout *l = new QHBoxLayout;
l->addWidget(progress);
QWidget *w = new QWidget;
w->setLayout(l);
grid->addWidget(w, 2, 1);