Manually place a toolbar Qt c++ - c++

My QMainWindow contains three different windows.
I would like to display three different toolbars. One for each window.
For now I display a toolbar but I can not place it just above my windows.
I wanted to know if it was possible?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent) {
//here I declared a widget and my three windows.
QToolBar *toolBar= addToolBar("window");
addLine=new QAction("Add Line",this);
removeLine=new QAction("Remove line",this);
removeAll=new QAction("Remove all",this);
toolBar->addAction(addLine);
toolBar->addAction(removeLine);
toolBar->addAction(removeAll);
}

Related

How does one split a QT(C++) UI into multiple widget subclasses and get it to display the same as all in the same class?

I'm learning QT (I already know C++ very well) and trying to get a UI to display well but I do not want to use the QT Designer that comes with QT Creator. I have the following class:
#include "MainPanel.h"
#include<QVBoxLayout>
MainPanel::MainPanel(QWidget *parent)
: QWidget(parent)
{
QLayout *lo = new QVBoxLayout(this);
mList = new QListWidget(this);
mList->addItem("Testing");
setLayout(lo);
lo->addWidget(mList);
lo->setSpacing(5);
}
The Main window class has a bunch of extra protected functions but the initControls method just does this:
void MainWindow::initControls()
{
QHBoxLayout *loMain = new QHBoxLayout(this);
loMain->addWidget(new MainPanel(this));
setLayout(loMain);
}
When I put all the code from MainPanel into MainWindow::initControls() or even in the constructor(either way), it works - shows a list widget with a single item "Testing". With the code in MainPanel though, it shows up as a very small rectangle that wouldn't fit the word "Testing" nor is there any semblance of text in there even partially.
I have tried to override sizeHint() in and move the code to create and return the list widget to a method getList() so I can access it from sizeHint too but that did nothing - I still get a small rectangle.
What am I doing wrong and what do I need to do or include to get the widget to paint properly? I have more controls I want to add to this UI (a button panel below the list widget and a detail panel on the right 2/3 of the window) but until I can get this to display, I can't possibly proceed with the rest.
I also want to do this entirely with code - not using the designer as I have vision issues and found it to be difficult to place things correctly on the form.
Someone please help - documentation and tutorials other than the documentation on QT's website is helpful if it points me to the right direction. I have already looked on QT's docs site under QWidget, QListWidget, QLayout, and QH(and V)BoxLayouts but see nothing and many of the tutorials talk about the designer.
Before someone tries to scold about creating a SSME or whatever small program - I have given you the smallest one that displays the issue - I know that putting the code all into the main window fixes it but one should never have everything in one class.
Okay, too unclear, what's happening there, we should have requested for more of your code =)
Here is the smallest possible sample, demonstrating what you should have been trying to achieve:
mainwindow.cpp:
#include "mainwindow.h"
#include "mainpanel.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
MainPanel* p = new MainPanel(this);
setCentralWidget(p);
}
mainpanel.h:
#include "mainpanel.h"
#include <QListWidget>
#include <QLayout>
MainPanel::MainPanel(QWidget *parent)
: QWidget(parent)
{
QLayout *lo = new QVBoxLayout(this);
QListWidget* mList = new QListWidget(this);
mList->addItem("Testing");
setLayout(lo);
lo->addWidget(mList);
lo->setSpacing(5);
}
main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.resize(400, 500);
w.show();
return app.exec();
}
Seemingly, you've tried to set a layout on QMainWindow, but it already has a built-in layout, it is exactly the case when setCentralWidget should work, leave manual layout creation for QWidget & QDialog subclasses.
The code above works fine, try it and refactor the way you want.
#MasterAler is correct that the root cause of your issue is setting a layout MainWindow. The reason for using a MainWindow is to support standard VBoxLayout of menubar, central widget, and status bar. So it makes no sense to set your own layout for a QMainWindow.
Since we didn't have your entire code, I didn't assume MainWindow was a QMainWindow. I got your code to work by making MainWindow a QDialog. This may be more of what you were originally looking for, where you want to put a widget of your own making into any container. Following is in Python (I find Python a faster prototyping environment than C++), but you can easily read it and see how to host your MainPanel is any widget (not just a MainWindow):
import sys
from PySide2.QtWidgets import QApplication, QWidget, QListWidget, QDialog, QVBoxLayout, QHBoxLayout
class MainPanel(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
lo = QVBoxLayout(self)
lo.setSpacing(5)
self.setLayout(lo)
mList = QListWidget(self)
mList.addItem("Testing")
lo.addWidget(mList)
class MainWindow(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
loMain = QHBoxLayout(self)
loMain.addWidget(MainPanel(self))
self.setLayout(loMain)
if __name__ == "__main__":
app = QApplication(sys.argv)
# Show the form
window = MainWindow(None)
window.exec_()

Qt C++ Creating toolbar

I am learning Qt and trying some examples in the book "Foundations of Qt Development".
In the book, there is a section teaching Single Document Interface with an example creating a simple app like a notepad.
However I am having problem with toolbar creating.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(QString("%1[*] - %2").arg("unnamed").arg("SDI"));
connect(ui->docWidget->document(), SIGNAL(modificationChanged(bool)), this, SLOT(setWindowModified(bool)));
createActions();
createMenu();
createToolbars();
statusBar()->showMessage("Done");
}
It is the constructor of the main window.
void MainWindow::createToolbars()
{
QToolBar* toolbar;
toolbar = addToolBar(tr("File"));
toolbar->addAction(anyaction);
}
This is how the book create the toolbar.
However, when I try to run the program, there are two toolbars created.
One is the toolbar created by the code and called "File"
Another is a blank toolbar created by the ui designer ie. *ui.toolbar.
In order to get rid of two toolbars, I tried using only the *ui.toolbar.
It's working. The code is shown below.
void MainWindow::createToolbars()
{
ui->toolBar->addAction(anyaction);
}
But I tried to create the toolbar by code only, ie. not adding a toolbar in the ui designer.
So I write this:
void MainWindow::createToolbars()
{
QToolBar* FileBar = this->addToolBar(tr("File"));
FileBar->addAction(anyaction);
}
However, there is a compile error.
The compiler use this function:
void QMainWindow::addToolBar(QT::ToolBarArea area, QToolBar * toolbar)
instead of what I want:
QToolBar * QMainWindow::addToolBar(const QString & title)
http://doc.qt.io/qt-5/qmainwindow.html#addToolBar-3
What is my mistake here?
When you removed QToolBar from MainWindow QtCreator automatically removed import of QToolBar class.
Just add this to the top of mainwindow.h:
#include <QToolBar>
And it is better to define QToolBar* FileBar in private section of MainWindow in mainwindow.h. Then you will be able to access it from any method of MainWindow class.
void MainWindow::createToolbars()
{
FileBar = this->addToolBar(tr("File"));
FileBar->addAction(anyaction);
}
When you see such message:
must point to class/struct/union/generic type
First of all try to include headers for necessary class.

QSystemTrayIcon shows only place holder and not the real icon

My code below brings up the icon but its like empty with nothing in it. if I move the mouse cursor over the expected icon location (last one) in system tray, its there but it doesn't show the real icon. It's more like just a place holder for the icon.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
systemTray = new QSystemTrayIcon();
systemTray->setIcon( QIcon::fromTheme("edit-undo") ); // stock icon but I have tried use local icon file too with same result
systemTray->setVisible( true ); // extra insurance
systemTray->show();
}
What am I doing wrong? I am using Qt 5.4 and Windows 7
I don't know why the stock icon doesn't work but it was a syntax and qmake issue. I had the path given as ":/icons/file.ico" or "icons/file.ico". The correct syntax is below otherwise it will not show the actual icon. Also I had to 'run qmake' apparently needed when new icon is added to qrc because even when the syntax was right, the problem was still there.
systemTray->setIcon( QIcon(":icons/file.ico") );

Create QAction with shortcut, without inserting in menu

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <cassert>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QAction* back = new QAction(this);
back->setVisible(true);
back->setShortcut(QKeySequence("Ctrl+M"));
bool cres = connect(back, SIGNAL(triggered(bool)), this, SLOT(mySlot()));
assert(cres);
}
In this code I tried to catch Ctrl+M key event. I don't want to put the action in menu. connect returns true but mySlot is never called. When action is inserted in menu, shortcut works well. What I have done wrong?
QAction is dormant until you insert it somewhere. As vahancho has suggested, use QShortcut. You need to instantiate the shortcut for each top-level widget (window) where you want it to be active. Thus if you have 5 top-level windows, you'll need 5 shortcuts, each having one of windows as its parent.
There is no way to use QShortcut as a global shortcut without the gui. QShortcut is only active when its associated widget has focus. The widget could be a top-level window.
System-global shortcuts are the subject of this question.

QT Creator Main window - how to change the interface for each element from the menu?

I am new to QT Creator. I did create a menu: Login || Open. When login is clicked I would like to see a line edit and a press button. When Open is clicked I would like to see a picture in the window. Can I change the interface of the same window depending on what I click in the menu bar? How can I do that?
I did something similar to this - an app with several major areas, toggled by an icon bar at the top.
I used a QStackWidget to stack the different application areas on top of each other, a set of QActions that I created using the designer, and a QActionGroup to implement the toggling.
When the actions are marked as "checkable" and grouped in a QActionGroup, theQToolBar only lets one be active at the time.
Here's a simplified extract of my code:
// MyApp.h
#include <QMainWindow>
class QAction;
class QActionGroup;
namespace Ui {
class MyApp;
}
class MyApp: public QMainWindow
{
Q_OBJECT
public:
explicit MyApp(QWidget *parent = 0);
~MyApp();
public slots:
void showSection(QAction* a);
private:
Ui::MyApp *ui;
QActionGroup* sections;
};
//MyApp.cpp
#include "structureapp.h"
#include "ui_structureapp.h"
#include <QActionGroup>
MyApp::MyApp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyApp),
sections(new QActionGroup(this)),
{
ui->setupUi(this);
/* Populate section list */
/* Page indices for the stack widget*/
ui->actionSectionOne-> setData(0);
ui->actionSectionTwo-> setData(1);
ui->actionSectionThree-> setData(2);
sections->addAction(ui->actionSectionOne);
sections->addAction(ui->actionSectionTwo);
sections->addAction(ui->actionSectionThree);
ui->mainToolBar->addSeparator();
connect(sections, SIGNAL(triggered(QAction*)), this, SLOT(showSection(QAction*)));
/* Show the default section */
ui->actionContentSection->trigger();
}
MyApp::~MyApp()
{
delete ui;
}
void MyApp::showSection(QAction *a)
{
ui->mainArea->setCurrentIndex(a->data().toInt());
}
Yes, you can. As I explained earlier, each menu entry is a signal, and that's connected to a slot. With two different menu entries, you have two signals, and you'd connect them to two different slots. So, you could name your first slot onLogin, and the second slot onOpen. (It helps to choose descriptive names, so you'll understand your program when you come back on mondays).
Now, it the slot onLogin, you put the code for login. In the slot onOpen, you put the other code. But do consider what happens if you click the two menu entries one after another. Should that even be possible? If not, you may need another solution. It's quite common to use a QDialog for a login. When a dialog is active, you can't use the menu of the main application, so you can't accidentily hit onOpen when you're busy with the login.