Segmentation fault when accessing the text of QLabel - qt

I got a problem with the QLabel. I got a QtWidget with a QLabel inside. Now I want to change the text of the Label with following code:
QLabel* safetyLabel = this->findChild<QLabel *>("safety_bits");
safetyLabel->setText(QString("test"));
printf("%i", (safetyLabel->text()).length());
but I always get a "Segmentation fault". I think it's something quite simple, but I just can't see it...
Any ideas?

Your safetyLabel can be NULL if you use QtCreators' designer to build your UI and execute your code before you call ui->setupUi(this); in MainWindows constructor.

Here is the code.
QLabel *safetyLabel = NULL;
safetyLabel = (QLabel *) this->findChild("safety_bits");
if(!safetyLabel)
{
qDebug() << "Failed to find safety_bits label!";
return 1;
}
safetyLabel->setText(QString("safety_bits is here"));

Related

Application crashing when searching for QLineEdit in QFormLayout

I've experienced a weird crash when trying to find a QLineEdit in a QFormLayout.
Firstly, I created a QFormLayout and set a name for it:
QFormLayout *charColLayout = new QFormLayout; charColLayout->setObjectName("charColLayout");
Then, I created a QLineEdit, modified it a bit and add it in to the layout, and I also give it a name:
QLineEdit *delim = new QLineEdit;
delim->setMaxLength(1);
delim->setMaximumWidth(100);
delim->setText("/");
delim->setObjectName("delEdit");
charColLayout->addRow("Delimiter", delim);
Afterward, in a completely different function, I re-searched that layout with findChild():
QFormLayout *charcoal = secondHoriField->findChild<QFormLayout *>("charColLayout", Qt::FindChildrenRecursively);
It should be noted that secondHoriField is just a normal QLayout which my QFormLayout is located in.
Finally, I attempted to find that QLineEdit:
QLineEdit *delimEdit = charcoal->findChild<QLineEdit*>("delEdit", Qt::FindChildrenRecursively);
if (delimEdit == nullptr) {cerr << "error\n";} //debug
string curDelim = qStrToStr(delimEdit->text());
And it surprisingly came down with a crash, and as the output shown, it's because the delimEdit is null.
18:06:10: Starting D:\...\build-cryptog-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\debug\cryptog.exe ...
error
18:06:17: The program has unexpectedly finished.
18:06:17: The process was ended forcefully.
18:06:17: D:\...\build-cryptog-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\debug\cryptog.exe crashed.
But when I switched the findChild() function for this rather bruteforce-y line:
QLineEdit *delimEdit = dynamic_cast<QLineEdit*>(charcoal->itemAt(1)->widget());
cerr << qStrToStr(delimEdit->objectName()) << endl; //debug line
The program ran fine, and it showed the same name I set for the QLineEdit:
18:12:02: Starting D:\...\build-cryptog-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\debug\cryptog.exe ...
delEdit
18:12:11: D:\...\build-cryptog-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\debug\cryptog.exe exited with code 0
Why did this happened?
Another note: qStrToStr() is a function I implement to convert QString to std::string, and I have hand-checked it.
While findChild is a QObject method the itemAt is a QFormLayout method.
QObject::findChild
QFormLayout::itemAt
With addRow you add an item to the QFormLayout. This does not make it a child in the context of the QObject.
QFormLayout::addRow
The purpose of the QFormLayout is to organize the positioning of QWidgets, it is not meant to serve as a container. Maybe you could check whether the top level QWidget (e.g. QMainWindow) holding the QFormLayout would be a better choice as a parent for the QLineEdit.
Assuming you have some kind of QMainWindow:
QMainWindow myMainWindow;
// ...
QLineEdit *delim = new QLineEdit(&myMainWindow);
delim->setObjectName("delEdit");
//...
In another location:
auto delimEdit = myMainWindow.findChild<QLineEdit*>("delEdit");

Processing signal of QTreeWidget that has QTreeWidgetItem derivitives as items

I didn't find a proper solution to this problem, so I hope somebody can give me an answer to my problem:
I am using a normal QTreeWidget, but as items I use an own subclass of QTreeWidgetItem (because I needed to store some other information in the item). Now I want to use the itemClicked() signal by the QTreeWidget, but I think my slot doesn't get any signal and I think it has to do with the signature of itemClicked(), since it sends a QTreeWidgetItem and of course not my own subclass.
Is it possible that QTreeWidget doesn't detect a click on my own subclass items?
Here is my connection:
connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *)), this, SLOT(displayTransformData(QTreeWidgetItem*)));
And here is my slot:
void GUI::displayTransformData(QTreeWidgetItem* item) {
cout << "test" endl;
Q_actorTreeWidgetItem* actor_item = dynamic_cast<Q_actorTreeWidgetItem*>(item);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor = actor_item->getActorReference();
double* position = new double[3];
position = actor->GetOrigin();
x_loc->setText(QString(std::to_string( position[0]).c_str() ));
}
I'm already trying to cast the item that I could get from the signal into my own subclass, but the slot function is never called, because the test from my cout line doesn't appear in the console.
I'm very grateful for every help!
The problem is your incorrect SIGNAL specification,
SIGNAL(itemClicked(QTreeWidgetItem *))
You should probably see a warning message at the console along the lines of:
QObject::connect: No such signal
tree_widget::itemClicked(QTreeWidgetItem *) in ...
From the documentation the actual signal spec is
void QTreeWidget::itemClicked(QTreeWidgetItem *item, int column)
So, using the old Qt4 syntax you need
connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
this, SLOT(displayTransformData(QTreeWidgetItem*)));
If possible, however, you should make use of the newer Qt5 signal/slot syntax
connect(treeWidget, &QTreeWidget::itemClicked, this, &GUI::displayTransformData);

How to get the text on qpushbutton?

I am loading .ui files via QUiloader, and showing the GUI in my application.
QWidget *mywidget = loader.load(file, this);
QList<QWidget*> wlist = mywidget.findChildren<QWidget *>()
I would like to know what is the text on QPushbutton. I know there is a method text() to get a text from Pushbutton, but it is not accessible when I do:
QString btext = wlist.at(1).text();
Any idea how I can get the text from QPushbutton, and other Widgets, when they grouped as QWidget?
Thanks.
You should search for QPushButtons instead of QWidgets:
QList<QPushButton*> blist = widget.findChildren<QPushButton*>();
Still your code wouldn't compile. The last line should read:
QString btext = blist.at(1)->text();
Using -> since you are accessing a pointer, not the widget. Also you should check if the findChildren() function actually returnes enough buttons. You would get a crash or assertions when accessing a list item by an invalid index.
Also please note that at(1) does not return the first but the second item in the list (lists start from 0).
Update: If you search for QWidgets and cast each of them you need to take care of getting a nullptr:
QList<QWidget*> wlist = widget.findChildren<QWidget*>();
foreach (QWidget* w, wlist)
{
QPushButton* b = dynamic_cast<QPushButton*>(w);
// If "w" is not a button "b" is nullptr
if (b)
{
QString btext = b->text();
}
}

Extracting icon using WinAPI in Qt app

I'm trying to extract icon from exe file using WinAPI, but it doesn't work.
Here's the code:
QIcon OSTools::AppsInterface::extractAppIcon(const QString &fileName) const {
wchar_t *convertedName = new wchar_t[fileName.length() + 1];
fileName.toWCharArray(convertedName);
convertedName[fileName.length()] = '\0';
HICON Icon = ExtractIcon(NULL, convertedName, 0);
QPixmap pixmap = QPixmap::fromWinHICON(Icon);
return QIcon(pixmap);
}
Code outputs:
QPixmap::fromWinHICON(), failed to GetIconInfo()
(ExtractIcon function on MSDN).
I think problem is that I send NULL instead of "A handle to the instance of the application calling the function". But, generally, I use Qt, and it's only one WinAPI function in my app.
What's wrong? What's correct way to extract icon using WinAPI? If you have another function proposal, please, give me an example. This is the first time I'm using WinAPI.
UPDATE: Yes, there is a better way. You may use QFileIconProvider class for doing such things.
Works for me, even with NULL. But obtaining the HINSTANCE is actually very simple. You have a problem elsewhere i guess. Does your target exe really have an embedded icon?
#ifdef Q_WS_WIN
#include <qt_windows.h>
#endif
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
#ifdef Q_WS_WIN
QString fileName("D:\\_dev\\eclipse\\eclipse.exe");
wchar_t *convertedName = new wchar_t[fileName.length() + 1];
fileName.toWCharArray(convertedName);
convertedName[fileName.length()] = '\0';
HINSTANCE hInstance = ::GetModuleHandle(NULL);
HICON Icon = ::ExtractIcon(hInstance, convertedName, 0);
ui->label->setPixmap(QPixmap::fromWinHICON(Icon));
#endif
}
I used QFileIconProvider, and it worked perfectly. Try this :
QPushButton b;
b.show();
QIcon icon;
QFileIconProvider fileiconpr;
icon = fileIconProvider.icon(QFileInfo("/*file name*/"));
b.setIcon(icon);
// And you can also save it where you want :
QPixmap pixmap = icon.pixmap( QSize(/*desired size*/) );
pixmap.save("/Desktop/notepad-icon.png");
Source. Have a nice day.
And solution was very simple. I just sent path to '.lnk' file instead of path to file. That's my inattention.

How can I get the selected VALUE out of a QCombobox?

In Qt, I can get the selected text of a QComboBox by using the
combobox->currentText() method.
How can I get the selected value?
I searched for help but I couldn't find a method currentData() which I expected to find. I could only find combobox->currentIndex()
Is there a smarter way to do it other than combobox->itemData(combobox->currentIndex())?
Update: This is no longer necessary as of Qt 5. A currentData() method has been added http://doc.qt.io/qt-5/qcombobox.html#currentData-prop
It seems you need to do combobox->itemData(combobox->currentIndex()) if you want to get the current data of the QComboBox.
If you are using your own class derived from QComboBox, you can add a currentData() function.
This one can get the text of current index:
QString cb = cbChoice ->currentText();
you can set QVariant data for all items, then you can get the value when you need it.
there is an example code for this situation:
ui.comboBoxSheetSize->addItem("128 m", QVariant(128));
ui.comboBoxSheetSize->addItem("256 m", QVariant(256));
ui.comboBoxSheetSize->addItem("512 m", QVariant(512));
ui.comboBoxSheetSize->addItem("1024 m", QVariant(1024));
...
void Page::onComboSheetSizeChanged( int index )
{
int value = ui.comboBoxSheetSize->itemData(index).toInt();
}
by the way, i think i misunderstood your question. i think the way you get data is smart enough?
The member function QComboBox::currentData has been added since this question was asked, see this commit
I had same issue
I have solved by
value = self.comboBox.currentText()
print value
This is my OK code in QT 4.7:
//add combobox list
QString val;
ui->startPage->clear();
val = "http://www.work4blue.com";
ui->startPage->addItem(tr("Navigation page"),QVariant::fromValue(val));
val = "https://www.google.com";
ui->startPage->addItem("www.google.com",QVariant::fromValue(val));
val = "www.twitter.com";
ui->startPage->addItem("www.twitter.com",QVariant::fromValue(val));
val = "https://www.youtube.com";
ui->startPage->addItem("www.youtube.com",QVariant::fromValue(val));
// get current value
qDebug() << "current value"<<
ui->startPage->itemData(ui->startPage->currentIndex()).toString();
I'm astonished that there isn't an activated signal and have the same problem. I solved it by making a subclass of QComboBox. I think it's better to avoid having to directly access the object and call its functions because that means more tight coupling and goes against Qt's philosophy. So here's the class I made that works for me.
class SmartComboBox : public QComboBox {
Q_OBJECT
private slots:
void triggerVariantActivated(int index);
public:
SmartComboBox(QWidget *parent);
signals:
void activated(const QVariant &);
};
And the implementation
void SmartComboBox::triggerVariantActivated(int index)
{
activated(itemData(index));
}
SmartComboBox::SmartComboBox(QWidget *parent)
:QComboBox(parent)
{
connect(this, SIGNAL(activated(int)), this, SLOT(triggerVariantActivated(int)));
}
The question is old, but maybe, somebody need an actual answer.
In the QGIS 3.4 you can get the value from the QComboBox with the method currentData().
Example: comboBox.currentData()
Link: https://doc.qt.io/qt-5/qcombobox.html#currentData-prop
I did this
QDir path("/home/user/");
QStringList _dirs = path.entryList(QDir::Dirs);
std::cout << "_dirs_count = " << _dirs.count() << std::endl;
ui->cmbbox->addItem(Files);
ui->cmbbox->show();
You will see with this that the QStringList named _dirs is structured like an array whose members you can access via an index up to the value returned by _dirs.count()
I had the issue and
QString str = m_UI->myComboBox->currentText();
solved this.
if you are developing QGIS plugins then simply
self.dlg.cbo_load_net.currentIndex()
I know I'm very late but for those who still have that problem, it can be solved easily.
I use Qt 5.3 and it works fine. No need to create a function or all that.
int valueComboBox;
valueComboBox = comboBox->currentIndex();
and it works !
Hope it helps !
I confirm the easiest way is to do this:
uiAnalyseAssets::AnalyseAssets(QWidget *parent)
: QWidget(parent)
{
ui.comboBox->addItem("text1");
ui.comboBox->addItem("text2");
...
}
void mainFunction::yourFunction( int index )
{
int value = ui.comboBox->currentText();
}

Resources