How to add text onto QToolbar with Qt Designer? - qt

I would like to ask, if it is possible to add some text onto QToolBar with Qt Designer?

You could do it in Qt Designer, but it'd be a bad hack an unnecessary. Instead, do it via code. There are two ways:
QToolBar is a widget that graphically represents actions, represented by QAction. You can add an action that is pure text, using the QToolBar::addAction(const QString &). E.g. if the toolbar object is simply called toolbar, you'd write toolbar->addAction("Some text");. This will create a button with given text, and return the corresponding action. Actions are an abstraction: they are devoid of a graphical representation, and they can be a part of multiple widgets (e.g. menus and toolbars). It's the individual widgets that give the actions some "physical shape", e.g. construct a button for each action.
QToolBar, at a lower level, is a collection of widgets, that you can add using QToolBar::addWidget(QWidget *). So, if you want to add some static text, you'd create a label with that text and add it to the toolbar. The action thus created may not seem very useful, since you won't be reacting to the user clicking the text (see p.1 above if you do). But it could be used to show and hide the text if desired, and acts as a handle for the text, allowing you to change the text as well. It is really a QWidgetAction derived class. See below for some code to get you started.
// The text can be empty, in case it was meant to be set sometime later
QAction *addText(QToolBar *toolbar, const QString &text = {})
{
auto *const label = new QLabel;
auto *const action = toolbar->addWidget(label);
// Any changes to the action's text should be propagated to the label.
QObject::connect(action, &QAction::changed, label, [action,label]{
label->setText(action->text());
});
action->setParent(toolbar); // so that the action won't leak
action->setText(text);
action->setVisible(true);
return action;
}
// inside some method
auto *action = addText(toolbar, "Some text");
// sometime later
action->setText("Some other text");
A more flexible way of doing this would be to derive QWidgetAction to create e.g. StaticTextAction, and put the label creation code into StaticTextAction::createWidget(). But such flexibility is most likely unnecessary, since all you're after here is some static text that applies to the toolbar and has no other use (e.g. you wouldn't add it to any other widgets or menus).

Related

Get text() from Widget in Layout

I have created widgets from code for the first time instead of through the creator. It reads in a text file and fills a QScrollArea widget with the material name (checkbox to enable it or not) and the thickness lineEdit, as seen in the picture. The number of widgets made corresponds to the number of entries in the text file.
I create the pushbuttons and checkboxes using the following function:
void overlayers::newField(QString material, bool checked, double thickness)
{
//Create new checkbox.
QCheckBox * checkbox = new QCheckBox(material);
checkbox->setChecked(checked);
//Create new field.
QLineEdit * line = new QLineEdit(QString::number(thickness));
//Create horizontal layout.
QHBoxLayout * layout = new QHBoxLayout();
layout->addWidget(checkbox,Qt::AlignLeft);
layout->addWidget(line,Qt::AlignRight);
//Add horizontal layout to vertical.
scrollLayout->addLayout(layout);
}
Where QVBoxLayout scrollLayout is defined in the class header.
I realised after doing the whole dialog box, I have to get the values from the fields and the checkbox flags to save the data but I have no idea how to iterate through all the checkboxes and lineEdits to get the text() and checkedState() variables!
I feel I have programmed this incorrectly and that there is a better way to do it. Is it possible to do this with how I have done it? If not, how would a better programmer do it re: creating the variable number of widgets and being able to access their data? A QVector sort of thing?
Thanks heaps!
http://i.stack.imgur.com/NKJVW.png

How can I customize the appearance of the actions in my QToolBar?

I have just changed some toolbars from Q3ToolBars (with QToolButtons explicitly added to them) into Q4 toolbars (with actions added to them straight away instead.)
The old tool buttons had a nice outline around them, but this is not displayed in the new version; the QActions in the Q4 toolbar just look like a line of icons. Is there a way to change the 'button' style in the new version (assuming these actions can be considered as such) and give them the outline? I've looked through the QToolBar reference, but the toolButtonStyle() function only appears to work with whether you want to display icon, text, etc.
...Or will I have to just make actual tool buttons and/or QPushButtons and use addWidget()?
The widget associated with a given action is accessible through QToolBar::widgetForAction (since Qt 4.2). So, you can pass your actions to this method, get the QWidgets returned by it, convert them to QToolBar, and handle them like you normally would (code not tested):
// ...
auto toolButton =
static_cast<QToolButton *>(
m_ui.toolbar->widgetForAction(m_ui.my_Action));
// Will make the toolButton always appear raised:
toolButton->setAutoRaise(false);
// ...
As far as I've been testing, some methods might not work (i.e., QWidget::hide), so do your own testing.
Yes, of course you can edit look of QToolButtons in two different ways:
You can set it style sheet using void QWidget::setStyleSheet(const QString &)
You can reimplement QToolButtons class with new paintEvent function where you will be able to exactly set how your button should looks like.

QAction vs QToolButton and when to override the Basic class?

I've recently been studying Qt, and have the following questions:
What is the difference between QAction and QToolButton?
How do I know when to override QPushButton? For example, should I override in order to be informed when the mouse enters a QPushButton's bounds? I don't need to in order to get the signal click().
Question 1:
QActions are used to define tasks performed by an application in a way which can be understood by a number of different user interface objects. Using an example from the Qt docs for context:
A QAction is defined; it is given an icon image, a text description, a keyboard shortcut and a longer tooltip description, as well as being linked to a user defined function.
newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
Later in the implementation, the QAction is added both to a textual menu bar...
fileMenu->addAction(newAct);
... and an icon-based tool bar:
fileToolBar->addAction(newAct);
The menu bar uses the text description to create an entry in the menu corresponding to the action. Similarly the toolbar uses the icon set on the QAction to create an icon in the toolbar which corresponds to the action. Selecting the menu item, clicking the toolbar icon or pressing the keyboard shortcut will all result in the same effect: that defined by the linking of QAction::triggered() to newFile().
So to directly answer your question: a QAction is an abstract way of defining the various parameters and behaviour of a particular task performed by the application. A QToolbarButton is a UI object (derived from QWidget) created by a QToolbar in response to QToolbar::addAction()
Question 2:
Yes, QPushButton has a clicked() signal inherited from QAbstractButton, but it does indeed lack a way to inform when the mouse has entered its bounds. You have a couple of options in order achieve this, but first you need to first set the mouseTracking property to be enabled. This will allow you to receive mouse move events on the QPushButton even if no mouse buttons are pressed. With that done you need to explore one of the following options:
As you suggest, you could subclass QPushButton and reimplement mousePressEvent in order to respond to the mouse position.
You could install another widget as an eventFilter on the QPushButton, and watch for events of type (QEvent::MouseMove).

Paste event in Qt

I want to build a structured document editor using Qt. The base concept for v1 is nested sections, each section having a title and one or more paragraphs. Sections and paragraphs are distinct visual units (probably via background shading). I also need to be able to store character-level semantics (ie: this run of text is associated with reference X). If I wanted to build a read-only view of this it would be doable with QFrame for the sections and a QLabel for each title and each paragraph. To make this editable I'm pretty sure I can capture all keyboard events to the window and implement a cursored text-entry-and-editing feel that way.
What I'm having trouble with is how to handle copy/paste.
I want the clipboard interactions to feel native: that is, ctrl+c/v on window, command+c/v on OSX, ctrl+c/v for clipboard on X, select to copy for PRIMARY on X, middle click to paste for PRIMARY on X, etc.
The standard text editing controls in Qt handle all of this just fine. I'm wondering if there is some sort of "paste event" or similar that I can grab to implement the same thing in my custom widget? Is there another way?
For native keyboard shortcuts, you can add them to menu items:
ui->actionCut->setShortcut(QKeySequence::Cut);
ui->actionCopy->setShortcut(QKeySequence::Copy);
ui->actionInsert_empty_row->setShortcut(Qt::Key_Insert);
ui->actionPaste->setShortcut(QKeySequence::Paste);
ui->actionRemove->setShortcut(QKeySequence::Delete);
See QKeySequence docs
There's no paste signal/event as far as i know to listen to, though there's nothing stopping you from taking a sneak look at how the paste() slot is implemented in widgets like QLineEdit and implement your own if possible. The afferent signal is not that important, since it's just a signal and you can trigger that whenever you desire(eg. Ctrl+v, context menu or program menu).
LE: If i think better, you might be thinking this the wrong way, you don't need a signal, you just need the slot that you can call whenever the action is called by any means you wish(eg. ctrl+v). Once you have the slot(QClipboard), it's just a matter of properly connecting it to the desired triggering actions/signals.
I'm not completely sure why you would want to do it with a QLabel and then capture the keys when there are already classes that handle text edition for you (and you can even override the key pressed funcionality)
If you want to have editable text, you could use a QTextEdit or a QPlainTextEdit and those classes already handle the copy-paste functionality (even with right click menu and everything).
If you want to add special a special behavior to your copy and paste, you can override the Mime functions:
//in your header file, add
void insertFromMimeData(const QMimeData *source) override; // override for paste
QMimeData * createMimeDataFromSelection() const override; // override for copy
// in the cpp:
//it would be something like this:
void YourTextField::insertFromMimeData(const QMimeData *source) {
// Do something special on the paste event, maybe even create your own "source"
//call the base class insert
QPlainTextEdit::insertFromMimeData(source);
}
Note: I'm not 100% with the copy, since I only overrode paste, but I'm almost certain that that's the right function.

QLabel embedding in QStatusBar using Qt Designer

Is there any solution to embed a QLabel in QStatusBar using Qt Designer?
I don't believe so. It's fairly simple to add one programmatically, though.
If you're just wanting to show a message, you could use: statusBar()->showMessage(tr("Message Here"));, or alternatively if you really needed a QLabel on the status bar, you could do something along the lines of:
QLabel *label = new QLabel("Message");
statusBar()->addWidget(label);
label would become a child of statusBar(), and appear in the first empty spot from the bottom left (addPermanentWidget(label) would add it to the first empty spot from the bottom right). If you place QLabel label in the classes header (or other var name), you'd be able to access the variable directly later (removing the initial QLabel type from the first line, of course).
It is not possible with Qt Designer. I resolve it by creating label a in Qt Designer and later in constructor of my MainWindows add this line:
Ui::"class name of my MainWindows"::"name of statusBar Object"->addWidget("Object Name of Label");
In my application, the class name of mainwindows is MainWindowsForm, the status bar is named statusBar and the label is named informationLabel. Then I have:
Ui::MainWindowsForm::statusBar->addWidget(informationLabel);
It's not possible even if you would manually edit UI file.

Resources