QT4.8 - Implement highlight to QLineEdit - c++

I am looking for a way to implement a highlighter for the QLineEdit widget.
I am using a QLineEdit to store a a path variable in my application, and I would to highlight environment variables.
Something like this:
${MY_ENVVAR}/foo/bar/myfile
Practically I would to have something like the QHightligher class.

Subclass QSyntaxHighliger
Write your own highlightBlock() method
Detect in your string this specific text which must be colored (you can do this for example by regular expression QRegExp) and use setFormat() method to paint string from x to x+n with some color
Helpful link: http://qt-project.org/doc/qt-4.8/qsyntaxhighlighter.html#highlightBlock
I never used highliter with QLineEdit before, so it can be impossible. But we can simply attach highliter to the QTextEdit. So we should create lineEdit from textEdit, there are many examples in web how to do that.
For example (I use code given by hyde with small additions.)
TextEdit.h
#ifndef TEXTEDIT_H
#define TEXTEDIT_H
#include <QTextEdit>
#include <QCompleter>
#include <QTextEdit>
#include <QKeyEvent>
#include <QStyleOption>
#include <QApplication>
class TextEdit : public QTextEdit
{
Q_OBJECT
public:
explicit TextEdit(QWidget *parent = 0)
{
setTabChangesFocus(true);
setWordWrapMode(QTextOption::NoWrap);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setFixedHeight(sizeHint().height());
}
void keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
event->ignore();
else
QTextEdit::keyPressEvent(event);
}
QSize sizeHint() const
{
QFontMetrics fm(font());
int h = qMax(fm.height(), 14) + 4;
int w = fm.width(QLatin1Char('x')) * 17 + 4;
QStyleOptionFrameV2 opt;
opt.initFrom(this);
return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
expandedTo(QApplication::globalStrut()), this));
}
};
#endif // TEXTEDIT_H
Usage (in the main.cpp)
#include "textedit.h"
//...
TextEdit *t = new TextEdit;
t->show();
new Highlighter(t->document());
Highlighter constructor as example
Highlighter::Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
}

Related

Show tooltip at mouse position and show legend on top-right corner

The following toy problem show two tabs, each tab contains a QGridLayout, which has a ScrollArea on one of the cells, which in turn contains a customized QLabel (MyLabel). When the user moves his mouse on the customzied QLabel, a tooltip shows up for several seconds.
test.pro
QT += core gui widgets
CONFIG += c++17
CONFIG += debug
QMAKE_CXXFLAGS += -std=c++17
SOURCES += \
test.cpp
QMAKE_CLEAN += $$TARGET Makefile
HEADERS += \
mywidget.h
test.cpp
#include "mywidget.h"
#include <QApplication>
#include <QtGui>
#include <QtCore>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyMainWindow myMainWindow;
myMainWindow.show();
return a.exec();
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QDebug>
#include <QWidget>
#include <QMdiArea>
#include <QMainWindow>
#include <QScrollArea>
#include <QLabel>
#include <QGridLayout>
#include <QMouseEvent>
#include <QToolTip>
class MyLabel : public QLabel
{
Q_OBJECT
public:
MyLabel(QWidget *parent=nullptr, const QString &name="")
: QLabel(parent), m_name(name)
{
resize(1800, 1200);
setMouseTracking(true);
}
private:
void mouseMoveEvent(QMouseEvent *ev) override {
QToolTip::showText(
ev->globalPosition().toPoint()
, m_name + ": " + QString::number(ev->pos().x()) + ", " + QString::number(ev->pos().y())
);
QLabel::mouseMoveEvent(ev);
}
private:
QString m_name;
};
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget* parent = nullptr, const QString &name="")
: QWidget(parent), m_name(name)
{
setWindowTitle(name);
m_gridLayout = new QGridLayout(this);
this->setLayout(m_gridLayout);
// layout col 1
m_gridLayout->addWidget(new QLabel("smaller label", this), 0, 0);
// layout col 2
m_scrollArea = new QScrollArea(this);
MyLabel *label = new MyLabel(this, m_name);
m_scrollArea->setWidget(label);
m_gridLayout->addWidget(m_scrollArea, 0, 1);
}
private:
QString m_name;
QGridLayout *m_gridLayout;
QScrollArea *m_scrollArea;
};
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public:
MyMainWindow(QWidget* parent = nullptr)
: QMainWindow(parent)
{
m_mdiArea = new QMdiArea(this);
this->setCentralWidget(m_mdiArea);
MyWidget *myWidget1 = new MyWidget(this, "widget 1");
m_mdiArea->addSubWindow(myWidget1);
MyWidget *myWidget2 = new MyWidget(this, "widget 2");
m_mdiArea->addSubWindow(myWidget2);
m_mdiArea->setViewMode(QMdiArea::ViewMode::TabbedView);
}
private:
QMdiArea *m_mdiArea;
};
#endif // MYWIDGET_H
Here are two problems that I am struggling with:
How can I show the tooltip without moving my mouse when I toggle between those two tabs by Ctrl+Tab? In my real-world problem, I use the tooltip show information about data at the mouse point.
Is it possible show some legends on the top-right corner of the viewport of the QScollArea, regardless of the positions of the scoll bars? I am trying with paintEvent, but had difficulties get the position adjusting according to scoll bars.
Cursor postion can be retrieved by using QCursor::pos(), so both problems can be sovlved by using QCuros::pos() in paintEvent. I was confused by the fact paintEvent does not directly provide cursor position, as mouseMoveEvent does.

How to make a canvas QWidget that can be zoomed and drawn on?

I'm trying to create a canvas to draw on with the mouse similar to most digital painting applications that I can also zoom in on (zoom in on the drawn image)
So far I've created a class that uses QWidget and added it to the ui then use the mouse events and QPaintEvent to draw on this widget which works. However the problem I'm not sure how do I zoom on this as well? I tried placing the QWidget inside of a scrollable area but it stops it from registering click events. I also tried extending from QGraphicsViewer instead of QWidget but this stops me from being able to paint as well.
//Class definition
PaintArea::PaintArea(QWidget *parent) : QWidget(parent)
{
this->setMouseTracking(true);
}
I'm mostly looking for a recommendation of how to scrolling and drawing with a mouse on the same widget (Possibly with scroll bar but just wheel scrolling for sure)
Thanks
If you follow the QWidget way, you may want to look carefully to the scribble example that is included with Qt docs. In this example, the drawing is made off-screen on a QImage object, which is then painted by the widget. The problem is to zoom the image.
I prefer your second way: QGraphicsView has a scale() function among many other excellent features. You may do something similar to the scribble example: draw off-screen on a QPixmap image which is set (every time you change the image) into a QGraphicsPixmapItem which belongs to the QGraphicsScene. I've implemented this crude example, borrowing some elements from the scribble example. Use the mouse wheel to zoom the image (it screws the scrolling a bit, sorry).
test.pro
QT += core gui widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
drawablescene.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
drawablescene.h \
mainwindow.h
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "drawablescene.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
void wheelEvent(QWheelEvent *event) override;
private:
QGraphicsView *m_view;
DrawableScene *m_scene;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QGraphicsView>
#include <QWheelEvent>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
m_view(new QGraphicsView(this)),
m_scene(new DrawableScene(this))
{
setCentralWidget(m_view);
m_scene->setSceneRect(0,0,640,480);
m_view->setScene(m_scene);
}
void MainWindow::wheelEvent(QWheelEvent *event)
{
qreal delta = 1 + (event->delta() > 0 ? 0.1 : -0.1);
m_view->scale(delta, delta);
event->accept();
}
drawablescene.h
#ifndef DRAWABLESCENE_H
#define DRAWABLESCENE_H
#include <QObject>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
class DrawableScene : public QGraphicsScene
{
public:
explicit DrawableScene(QObject *parent = nullptr);
private:
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void drawLineTo(const QPointF &endPoint);
bool m_modified;
bool m_scribbling;
int m_penWidth;
QColor m_penColor;
QPointF m_lastPoint;
QPixmap *m_image;
QGraphicsPixmapItem *m_item;
};
#endif // DRAWABLESCENE_H
drawablescene.cpp
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include "drawablescene.h"
DrawableScene::DrawableScene(QObject *parent)
: QGraphicsScene(parent),
m_modified(false),
m_scribbling(false),
m_penWidth(3),
m_penColor(Qt::blue)
{
m_image = new QPixmap(640, 480);
m_image->fill(Qt::white);
m_item = addPixmap(*m_image);
}
void DrawableScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if ((event->buttons() & Qt::LeftButton) && m_scribbling) {
drawLineTo(event->scenePos());
event->accept();
}
else QGraphicsScene::mouseMoveEvent(event);
}
void DrawableScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_lastPoint = event->scenePos();
m_scribbling = true;
event->accept();
}
else QGraphicsScene::mousePressEvent(event);
}
void DrawableScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton && m_scribbling) {
drawLineTo(event->scenePos());
m_scribbling = false;
event->accept();
}
else QGraphicsScene::mouseReleaseEvent(event);
}
void DrawableScene::drawLineTo(const QPointF &endPoint)
{
QPainter painter(m_image);
painter.setPen(QPen(m_penColor, m_penWidth, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin));
painter.drawLine(m_lastPoint, endPoint);
m_modified = true;
m_lastPoint = endPoint;
m_item->setPixmap(*m_image);
}

Is there a Qt widget that looks like a label to display text but can also be edited if double-clicked?

I want a widget in Qt that will act like a spreadsheet cell does. It can display text, then when the user double-clicks on it, it becomes editable. Once the user is done with editing and presses Enter, the text gets saved and the control is not editable anymore. If the user hits Escape while editing, then the control returns to its previous value.
One possible solution is sub-classing QWidget, QLabel and QLineEdit. Are there any other solutions available in Qt?
The following version also implements the same functionalities of your answer but instead of subclassing the QLineEdit and the QLabel only use eventFilter() and instead of managing the visibility manually let QStackedWidget do it.
#include <QApplication>
#include <QFormLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QStackedWidget>
#include <QVBoxLayout>
class MyEditableLabel: public QWidget{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
MyEditableLabel(QWidget *parent=nullptr):
QWidget(parent),
mLabel(new QLabel),
mLineEdit(new QLineEdit)
{
setLayout(new QVBoxLayout);
layout()->setMargin(0);
layout()->setSpacing(0);
layout()->addWidget(&stacked);
stacked.addWidget(mLabel);
stacked.addWidget(mLineEdit);
mLabel->installEventFilter(this);
mLineEdit->installEventFilter(this);
setSizePolicy(mLineEdit->sizePolicy());
connect(mLineEdit, &QLineEdit::textChanged, this, &MyEditableLabel::setText);
}
bool eventFilter(QObject *watched, QEvent *event){
if (watched == mLineEdit) {
if(event->type() == QEvent::KeyPress){
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Return ||
keyEvent->key() == Qt::Key_Escape ||
keyEvent->key() == Qt::Key_Enter)
{
mLabel->setText(mLineEdit->text());
stacked.setCurrentIndex(0);
}
}
else if (event->type() == QEvent::FocusOut) {
mLabel->setText(mLineEdit->text());
stacked.setCurrentIndex(0);
}
}
else if (watched == mLabel) {
if(event->type() == QEvent::MouseButtonDblClick){
stacked.setCurrentIndex(1);
mLineEdit->setText(mLabel->text());
mLineEdit->setFocus();
}
}
return QWidget::eventFilter(watched, event);
}
QString text() const{
return mText;
}
void setText(const QString &text){
if(text == mText)
return;
mText == text;
emit textChanged(mText);
}
signals:
void textChanged(const QString & text);
private:
QLabel *mLabel;
QLineEdit *mLineEdit;
QStackedWidget stacked;
QString mText;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QFormLayout *lay = new QFormLayout(&w);
MyEditableLabel el;
lay->addRow("MyEditableLabel: ", &el);
lay->addRow("QLineEdit: ", new QLineEdit);
w.show();
return a.exec();
}
#include "main.moc"
this solution is not as sexy but probably one of the more performant solutions available to you is to use a QInputdialog to change QLabel and override the mouseDoubleClickEvent to trigger the input dialog. I as some here have learned that there is no means to Pull edited text from a QLabel. Not without changing QLabels internal code. Here's an example using a QInputDialog as means.
//intrlbl.h
#ifndef INTRLBL_H
#define INTRLBL_H
#include <QWidget>
#include <QLabel>
#include <QMouseEvent>
class intrLbl: public QLabel
{
Q_OBJECT
public:
intrLbl(QWidget *parent);
void mouseDoubleClickEvent(QMouseEvent *event) override;
QString text;
};
#endif // INTRLBL_H
//intrlbl.cpp file
#include "intrlbl.h"
#include <QDebug>
#include <QInputDialog>
intrLbl::intrLbl(QWidget *parent)
{
this->setText("Text Changeable Via Double Click QInput Dialog");
this->setFocusPolicy(Qt::ClickFocus);
this->setWordWrap(false);
}
void intrLbl::mouseDoubleClickEvent(QMouseEvent *event)
{
QString title
= QInputDialog::getText(this,
tr("Enter your Idea Title:"),
tr("Title:"), QLineEdit::Normal,
tr("enter your title here"));
if(!title.isEmpty())
{
qDebug() << "Title set to:" << title;
this->setText(title);
}
else
{
title = "Title";
this->setText(title);
}
}
One of the solutions is to have a QLineEdit and set it to read-only and style it in a way that it will look like a label. I personally do not like this solution, because it's more of a hacking approach. I have come up with something that in my opinion is pretty cool, which includes sub-classing QWidget, QLabel and QLineEdit:
Let's first introduce a model, which will be created in the sub-classed version of our QWidget and this model will be passed to its child widgets, the sub-classed versions of QLabel and QLineEdit:
Model header - mymodel.h:
#ifndef MYMODEL_H
#define MYMODEL_H
#include <QObject>
class MyModel : public QObject {
Q_OBJECT
Q_PROPERTY(Mode mode READ getMode WRITE setMode NOTIFY modeChanged)
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
public:
enum class Mode {
ReadOnly = 0,
Edit = 1,
};
explicit MyModel(QObject* parent = nullptr);
Mode getMode() const {
return _mode;
}
const QString& getText() const {
return _text;
}
signals:
void modeChanged(Mode mode);
void textChanged(const QString& text);
public slots:
void setMode(Mode mode);
void setText(const QString& text);
private:
Mode _mode;
QString _text;
};
#endif // MYMODEL_H
Model implementation - mymodel.cpp
#include "mymodel.h"
MyModel::MyModel(QObject *parent)
: QObject(parent)
, _mode(MyModel::Mode::ReadOnly)
, _text(QString()) {
}
void MyModel::setMode(MyModel::Mode mode) {
if (_mode != mode) {
_mode = mode;
emit modeChanged(_mode);
}
}
void MyModel::setText(const QString &text) {
if (_text != text) {
_text = text;
emit textChanged(text);
}
}
As we see the model has the text, which is common for both the QLabel and the QLineEdit, and it has a mode, which can be either read only or edit mode.
The label implementation is a sub-class of Label.
Header - mylabel.h:
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
#include <QSharedPointer>
#include "mymodel.h"
class MyLabel : public QLabel {
Q_OBJECT
public:
explicit MyLabel(QWidget *parent = 0);
void setModel(QSharedPointer<MyModel> model);
protected:
void mouseDoubleClickEvent(QMouseEvent *) override;
private:
QSharedPointer<MyModel> _model;
};
#endif // MYLABEL_H
Implementation - mylabel.cpp:
#include "mylabel.h"
#include <QMouseEvent>
MyLabel::MyLabel(QWidget *parent)
: QLabel(parent) {
}
void MyLabel::setModel(QSharedPointer<MyModel> model) {
_model = model;
}
void MyLabel::mouseDoubleClickEvent(QMouseEvent *) {
_model->setText(text());
_model->setMode(MyModel::Mode::Edit);
}
As we our class MyLabel has a setModel() method, which will take the model from its parent. We are overriding the mouseDoubleClickEvent(), though which we are setting the text of the model to whatever text there is in the label, and setting the mode to edit, because when double-clicking we want to edit the text.
Now let's take a look at the QLineEdit. Our version of QLineEdit, called MyLineEdit, is listening to keyboard events and when Enter and Esc keys are pressed it either saves the text to the model, or discards it. Then it changes the mode to read-only.
MyLineEdit.h:
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QLineEdit>
#include <QSharedPointer>
#include "mymodel.h"
class MyLineEdit : public QLineEdit {
Q_OBJECT
public:
MyLineEdit(QWidget* parent = nullptr);
void setModel(QSharedPointer<MyModel> model);
protected:
void keyPressEvent(QKeyEvent* event) override;
void focusOutEvent(QFocusEvent*);
private:
QSharedPointer<MyModel> _model;
};
#endif // MYLINEEDIT_H
And here's the implementation - MyLineEdit.cpp:
#include "mylineedit.h"
#include <QKeyEvent>
MyLineEdit::MyLineEdit(QWidget *parent)
: QLineEdit(parent) {
}
void MyLineEdit::setModel(QSharedPointer<MyModel> model) {
_model = model;
}
void MyLineEdit::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Enter) {
_model->setText(text());
_model->setMode(MyModel::Mode::ReadOnly);
} else if (event->key() == Qt::Key_Escape) {
_model->setMode(MyModel::Mode::ReadOnly);
} else {
QLineEdit::keyPressEvent(event);
}
}
void MyLineEdit::focusOutEvent(QFocusEvent *) {
_model->setText(text());
_model->setMode(MyModel::Mode::ReadOnly);
}
So now we have the model, we have our version of QLabel and our version of QLineEdit. What we want now is a parent widget that will contain both of them, listen to signals from the model and change its appearance based on the signals. That class is derived from QWidget and is called MyEditableLabel:
MyEditableLabel.h:
#ifndef MYEDITABLELABEL_H
#define MYEDITABLELABEL_H
#include <QSharedPointer>
#include <QWidget>
#include "mylabel.h"
#include "mylineedit.h"
class MyEditableLabel : public QWidget {
Q_OBJECT
public:
explicit MyEditableLabel(QWidget *parent = nullptr);
QString getText() const {return _text;}
private:
MyLabel *_label;
MyLineEdit *_lineEdit;
QSharedPointer<MyModel> _model;
private slots:
void onModeChanged(MyModel::Mode mode);
void onTextChanged(const QString &text);
private:
QString _text;
};
#endif // MYEDITABLELABEL_H
MyEditableLabel.cpp:
#include "myeditablelabel.h"
#include <QHBoxLayout>
MyEditableLabel::MyEditableLabel(QWidget *parent)
: QWidget(parent) {
_model = QSharedPointer<MyModel>(new MyModel());
_model->setText("Click me!");
_label = new MyLabel(this);
_label->setModel(_model);
_lineEdit = new MyLineEdit(this);
_lineEdit->setModel(_model);
_lineEdit->setReadOnly(false);
QHBoxLayout *mainLayout = new QHBoxLayout();
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
mainLayout->addWidget(_label);
mainLayout->addWidget(_lineEdit);
setLayout(mainLayout);
connect(_model.data(), &MyModel::modeChanged, this, &MyEditableLabel::onModeChanged);
onModeChanged(_model->getMode());
connect(_model.data(), &MyModel::textChanged, this, &MyEditableLabel::onTextChanged);
onTextChanged(_model->getText());
}
void MyEditableLabel::onModeChanged(MyModel::Mode mode) {
_lineEdit->setVisible(mode == MyModel::Mode::Edit);
_lineEdit->selectAll();
_label->setVisible(mode == MyModel::Mode::ReadOnly);
}
void MyEditableLabel::onTextChanged(const QString &text) {
_lineEdit->setText(text);
_label->setText(text);
_text = text;
}
Usage:
Using this is pretty straightforward. If you're using the Qt Creator designer, then you want to draw a QWidget and the right click on it and promote it to MyEditableLabel and you're done. If you're not using the Qt Creator designer then you just have to create and instance of MyEditableLabel and you're in business.
Improvements:
It probably is a better idea to not create the model in the constructor of MyEditableLabel, but outside of it and have a setModel method in MyEditableLabel.

QToolButton not visible in windows

I have derived the class of QTabBar to implement "+" (new tab button) button using QToolButton (similar to google chrome). However, it is working in my Linux machine but doesn't work in my windows machine. By not working I mean QToolButton is not visible in my windows machine but it is visible in my Linux machine (Ubuntu). I am not able to debug it further as I have tried few experiments to understand the reason but it didn't work.
My Source file:
#include "tabbar.h"
TabBar::TabBar(QWidget *parent) : QTabBar(parent)
{
new_button_ = new QToolButton(this);
new_button_->setObjectName(QStringLiteral("AddButton"));
new_button_->setText("+");
new_button_->setFixedSize(QSize(20, 20));
connect(new_button_, SIGNAL(released()), this, SLOT(emit_new()));
movePlusButton();
}
QSize TabBar::sizeHint(void) const
{
QSize old = QTabBar::sizeHint();
return QSize(old.width() + 45, old.height());
}
void TabBar::emit_new(void)
{
emit newClicked();
}
void TabBar::movePlusButton(void)
{
quint64 totalWidth = 0;
for (long i=0; i < count(); i++)
totalWidth += tabRect(i).width();
quint64 h = geometry().top();
quint64 tab_height = height();
quint64 w = width();
if (totalWidth > w)
new_button_->move(w-40, tab_height - 30);
else
new_button_->move(totalWidth + 5, tab_height - 30);
}
void TabBar::resizeEvent(QResizeEvent *p_evt)
{
QTabBar::resizeEvent(p_evt);
movePlusButton();
}
void TabBar::tabLayoutChange(void)
{
QTabBar::tabLayoutChange();
movePlusButton();
}
My Header File:
#ifndef TABBAR_H
#define TABBAR_H
#include <QObject>
#include <QToolButton>
#include <QTabBar>
#include <QResizeEvent>
#include <QLabel>
class TabBar : public QTabBar {
Q_OBJECT
public:
TabBar(QWidget *parent=nullptr);
~TabBar() { }
void movePlusButton(void);
void resizeEvent(QResizeEvent *p_evt) override;
void tabLayoutChange(void) override;
QSize sizeHint(void) const override;
private slots:
void emit_new(void);
signals:
void newClicked(void);
private:
QToolButton *new_button_;
};
#endif // TABBAR_H
EDIT:
I have tried few more experiments and got to know QToolButton is hiding behind region next to Tab bars. Please refer the screenshot.
Apparently, your application uses a stylesheet or something to customize the display and this is incompatible with your TabBar class.
Downloaded your code, wrote a simple main:
#include <QApplication>
#include <QMainWindow>
#include "tabbar.h"
int main( int argc, char* argv[] )
{
QApplication app(argc, argv);
QMainWindow wnd;
TabBar* tabBar = new TabBar(&wnd);
wnd.setCentralWidget( tabBar );
tabBar->addTab( "Foo" );
wnd.show();
return app.exec();
}
compiled and executed on Windows and got that (tested classic and aero style):
So apparently your code is fine. However, if you customized the QTabBar rendering through a stylesheet (what I suspect when I see how it looks in your GUI), you may need to adapt yourcode (probably movePlusButton as it has some values hardcoded that may be incompatible with the current display style):
if (totalWidth > w)
new_button_->move(w-40, tab_height - 30);
else
new_button_->move(totalWidth + 5, tab_height - 30);

I am getting two errors but I cannot identify them

I am a novice to c++, but I am doing my best to learn.
I am getting two errors and I don't know why, these are:
In constructor 'MyLabel::MyLabel(QWidget*)':
Qualified-id in declaration before '(' token -line 7
Qualified-id in declaration before '(' token -line20
My code is as follows:
mylabel.cpp:
#include "mylabel.h"
#include "ui_mainwindow.h"
MyLabel::MyLabel(QWidget *parent) :
QWidget(parent)
{
void MyLabel::MyLabel()
{
this->setAlignment(Qt::AlignCenter);
//Default Label Value
this->setText("No Value");
//set MouseTracking true to capture mouse event even its key is not pressed
this->setMouseTracking(true);
}
void MyLabel::mouseMoveEvent(QMouseEvent * event)
{
//Show x and y coordinate values of mouse cursor here
this->setText("X:" + QString::number(event->x()) + "-- Y:" + QString::number(event->y()));
}
}
mylabel.h:
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QObject>
#include <QApplication>
#include <QMainWindow>
#include <QMouseEvent>
class MyLabel : public QWidget
{
Q_OBJECT
public:
explicit MyLabel(QWidget *parent = 0);
~MyLabel();
void mouseMoveEvent(QMouseEvent * event);
signals:
};
#endif // MYLABEL_H
main.cpp
#include "mainwindow.h"
#include "mylabel.h"
#include <QApplication>
#include <QHBoxLayout>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow *window = new QMainWindow();
window->setWindowTitle(QString::fromUtf8("QT - Capture Mouse Move"));
window->resize(300, 250);
QWidget *centralWidget = new QWidget(window);
QHBoxLayout* layout = new QHBoxLayout(centralWidget);
MyLabel* CoordinateLabel = new MyLabel();
layout->addWidget(CoordinateLabel);
window->setCentralWidget(centralWidget);
window->show();
return app.exec();
}
mainwindow.cpp is blank
You are getting error are you are trying to define functions inside your constructor. MyLabel::MyLabel(QWidget *parent) so be
MyLabel::MyLabel(QWidget *parent) : QWidget(parent)
{
this->setAlignment(Qt::AlignCenter);
//Default Label Value
this->setText("No Value");
//set MouseTracking true to capture mouse event even its key is not pressed
this->setMouseTracking(true);
}
And then the definition for mouseMoveEvent should follow after the constructor
void MyLabel::mouseMoveEvent(QMouseEvent * event)
{
//Show x and y coordinate values of mouse cursor here
this->setText("X:" + QString::number(event->x()) + "-- Y:" + QString::number(event->y()));
}
EDIT:
As pointed out in the comments setAlignment and setText are not members of QWidget so if they are not members of MyLable then you will need to remove those otherwise it will not compile.
In order to implement your custom label you have to derive your class from Qt's standard QLabel class as:
class MyLabel : public QLabel
{
Q_OBJECT
public:
explicit MyLabel(QWidget *parent = 0);
~MyLabel();
protected:
void mouseMoveEvent(QMouseEvent * event);
};
Unfortunately in C++ you can not define a function inside another function as you did in MyLabel::MyLabel() constructor. Just write it in the following way:
MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
{
setAlignment(Qt::AlignCenter);
//Default Label Value
setText("No Value");
//set MouseTracking true to capture mouse event even its key is not pressed
setMouseTracking(true);
}
UPDATE
I would implement the handling of the mouse move event in this way:
void MyLabel::mouseMoveEvent(QMouseEvent * event)
{
// Show x and y coordinate values of mouse cursor here
QString txt = QString("X:%1 -- Y:%2").arg(event->x()).arg(event->y());
setText(txt);
}