Menubar is not showing on the second window - qt

I am trying to build an application that after getting some user input on the first window, pops up another window and displays some results. However, even though the menubar is visible on the first window, the menubar does not appear on the second window. The two windows are objects of different classes, but both classes are inherited from QMainWindow.
I have tried using the menuBar() function which returns a pointer for the menubar to add menus (this works for the first window). I also tried creating a new menubar object which didn't help either.
//MapWindow.h
class MapWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MapWindow(QWidget *parent = nullptr);
~MapWindow();
private:
QAction *vehicleAct;
QAction *missionAct;
QAction *backAct;
QMenu *toolMenu;
};
//MapWindow.cpp
MapWindow::MapWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MapWindow)
{
ui->setupUi(this);
setWindowState(Qt::WindowMaximized);
vehicleAct = new QAction("Vehicle Selection");
vehicleAct->setShortcut(Qt::CTRL + Qt::Key_V);
missionAct = new QAction("Mission Selection");
missionAct->setShortcut(Qt::CTRL + Qt::Key_M);
backAct = new QAction("Back");
backAct->setShortcut(Qt::CTRL + Qt::Key_B);
toolMenu = menuBar()->addMenu("Tools");
toolMenu->addAction(vehicleAct);
toolMenu->addAction(missionAct);
toolMenu->addAction(backAct);
}
MapWindow::~MapWindow() {
delete ui;
}
When I use the same code in the WelcomeWindow class which is also inherited from QMainWindow it works perfectly. However it doesn't even show a menubar in this second window.

I managed to find the problem. One of my widgets (QScrollArea) was located in the top left corner of the screen which was stopping the whole menubar from displaying for some reason. Moving the QScrollArea down a little bit has solved the problem.

Related

How to make QToolButton go beyond the edge of QToolbar?

How can I make the button go beyond the edge of QToolbar?
Below is the code as I create the toolbar:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0)
private:
QToolBar* _toolBar;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
_toolBar = new QToolBar;
QAction *actionAdd = new QAction(QIcon(":/images/add.png"), "", this);
_toolBar->addAction(actionAdd);
addToolBar(Qt::ToolBarArea::TopToolBarArea, _toolBar);
}
style.qss
QToolBar {
background: #018ac4;
height: 150px;
}
As said before, it is not possible to solve this correctly using QtWidgets.
However I see two options to visually create that effect:
Take the button out of the tool bar and add it to the main window instead, but do not add it to a layout. Usually i would say reposition it on resize events, but since it is in the top left, you might as well just call setGeometry() once on startup and not worry about it later. You probably have to add last, or call rise() though.
Make it look like the button sticks out, while it really doesn't. Make the toolbar as large as the button, but paint the lower part of the toolbar in the brighter blue, so that it looks like it is part of the widget below it.
It is not possible with widgets. A QWidget can not paint outside of its area. See this answer : https://stackoverflow.com/a/48302076/6165833.
However, the QToolBar is not really the parent of the QAction because addAction(QAction *action) does not take the ownership. So maybe the QMainWindow could paint your QAction the way you want but AFAIK this is not doable through the public API of Qt.
What you could do is use QML (but you would need to use QML for the whole window then).

Qt - QStackedLayout setCurrentIndex displays blank window instead of widget

I just started learning Qt a couple days ago to make a game, and I'm trying to figure out how to make layouts work.
What I want is a Window using QStackedLayout with 2 widgets inside: StartScreen and GameScreen. StartScreen is shown on top on program run. A button in StartScren is connected to a function inside Window, and Window will call setCurrentIndex to change the widget on top to GameScreen.
What happens right now is that when I click on the button, the view changes to a blank window. I've tried hardcoding to setCurrentIndex(0), which does nothing, setCurrentIndex(1), which is what GameScreen should be and displays the same blank window, and setCurrentIndex(2), which is out of index bounds but still does nothing. So the connection is going through, but I don't understand why a blank window will show up instead of the button I have on GameScreen.
If someone can explain to me what concept I missed and how to fix it, I'd greatly appreciate it. Thanks!
Here is window.cpp:
Window::Window(QWidget *parent) : QWidget(parent)
{
resize(640, 480);
layout = new QStackedLayout;
createStartScreen();
createGameScreen();
setLayout(layout);
show();
};
void Window::createStartScreen(){
start = new StartScreen();
layout->addWidget(start);
start->setWindow(this);
}
void Window::playGame(){
layout->setCurrentIndex(layout->indexOf(game));
}
void Window::createGameScreen(){
game = new GameScreen();
layout->addWidget(game);
}
startscreen.cpp:
StartScreen::StartScreen(QWidget *parent) : QWidget(parent)
{
newGameButton = new QPushButton("New Game", this);
newGameButton->setGeometry(QRect(QPoint(260, 300), QSize(120,40)));
quitButton = new QPushButton("Quit", this);
quitButton->setGeometry(QRect(QPoint(260, 360), QSize(120,40)));
connect(quitButton, SIGNAL(clicked()), QApplication::instance(), SLOT(quit()));
};
void StartScreen::setWindow(Window *w){
connect(newGameButton, SIGNAL(clicked()), w, SLOT(playGame()));
}
gamescreen.cpp:
GameScreen::GameScreen(QWidget *parent) : QWidget(parent)
{
button = new QPushButton("Hi");
button->setGeometry(QRect(QPoint(260, 260), QSize(120,40)));
};
That's because you don't call show on button. But you should rather use a layout to handle it.
e.g.:
GameScreen::GameScreen(QWidget *parent)
: QWidget(parent)
{
button = new QPushButton(tr("Hi"));
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(button);
};
button will have a size adapted to its text and will be cleaned positioned in GameScreen.
On a side note, you should rather add a signal to StartScreen to request a new game and do the connection in Window. That way you won't have a tight coupling between StartScreen and Window.

Qt: Resizing QMenuBar corner widget

I put a push button into the top-right corner of my main window menu bar:
QPushButton *pb = new QPushButton("Text");
pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
QMainWindow *mainWindow;
mainWindow->menuBar()->setCornerWidget(pb, Qt::TopRightCorner);
The initial layout is fine. Sometime later, an asynchronous event changes the QPushButton's text to a longer string, but it gets clipped on the right.
I can see that the QPushButton's size changes when the string is updated. The QPushButton is displayed correctly if the window is resized. The problem appears to be getting the QMenuBar to recognize that the widget's size has changed.
This answer How to auto change QPushButton width and QMenuBar corner widget width when change text of button? suggests resetting the corner widget. I would rather avoid that, because my application's structure makes me jump through several ugly and awkward hoops to reset the corner widget after initializing.
The solution is simple. After updating the text of the button call menuBar()->adjustSize(); I have tested it in Qt5.5 and hope it will work for you.
You can use QWidgetAction as a horizontal menu widget:
class TestMenu : public QWidgetAction
{
public:
TestMenu(QObject *parent) :
QWidgetAction (parent)
{
}
virtual QWidget *createWidget(QWidget *parent)
{
QComboBox *combo = new QComboBox(parent);
combo->setFixedWidth(300);
return combo;
}
virtual void deleteWidget(QWidget *widget)
{
delete widget;
}
};
...
QMenu *menu = new QMenu();
menu->addAction(new TestMenu(this));
menuBar()->setCornerWidget(menu);

QGraphicsView does not show anything in Qt 5.0

I am new to Qt 5.0 and I am trying to use a QGraphicsView called "missionView" of size 700x400 inside a QWidget to show a rectangle. However, nothing shows up inside the graphics view on running the application. Here is the constructor of the QWidget "MainView" where I am doing everything
MainView::MainView(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainView)
{
ui->setupUi(this);
QGraphicsScene scene(0, 0, 500, 500);
QGraphicsRectItem* myrect = scene.addRect(QRectF(0,0,15,5),QPen(), QBrush());
ui->missionView->setScene(&scene);
ui->missionView->setVisible(true);
ui->missionView->show();
ui->missionView->update();
printf("QGraphicsScene scene's items: %d\n",scene.items().size());
for (int i = 0; i < scene.items().size(); i++) {
printf("%d\n",scene.items().at(i));
}
}
The last print statement does show that one item has been added but still nothing gets shown. I have tried an approach similar to this but this too dosent work. Can anyone please explain this.
You're creating the scene object on the stack.
Thus the scene will be destroyed right away at the end of the constructor and thus nothing will be shown.
Create the scene on the heap and/or make it a class member and it should work.

Put QMenuBar at QMainWindow Bottom in QT

Is there any way to put a QMenuBar at screen bottom (I mean, at QMainWindow bottom)?
I'm working on my thesis project, and my director asked me to put a QMenuBar at screen bottom. Is this possible?, I have been trying adjusting the menubar geometry. In Qt Designer I can move the bar position, but when I run my project, the menu bar is always up.
Thanks in advance.
Don't use the default QMenuBar provided with the QMainWindow. Instead create your own. This proof of concept example creates a new QMenuBar which is added to a QVBoxLayout which was added to the mainwindow:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* bar = new QMenuBar(this);
ui->verticalLayout->addWidget(bar);
QMenu* menu1 = new QMenu("First menu", bar);
menu1->addMenu("Foo");
menu1->addMenu("Bar");
QMenu* menu2 = new QMenu("Second menu", bar);
menu2->addMenu("Foo");
menu2->addMenu("Bar");
bar->addMenu(menu1);
bar->addMenu(menu2);
}
This works at least in Windows.
I've placed menus in the QDockWidget so I assume it is also possible to place menu bar at the bottom.
But you must do it programmaticaly. QMenuBar inherits QWidget, so just add a QWidget at the bottom of QMainWindow, then create a QMenuBar specifying this QWidget as a parent widget.

Resources