不使用线程的 C++/Qt 线程错误
Posted
技术标签:
【中文标题】不使用线程的 C++/Qt 线程错误【英文标题】:C++/Qt Threads error without using threads 【发布时间】:2015-07-21 09:22:31 【问题描述】:我正在使用一种特殊形式的 qt 框架,它看起来会有些复杂。不过别担心。和qt原来的框架是一样的。 (不,我不能改变它)
我的这个程序的目的是从 ui 加载一个 tableview
中的表。 tableview
的行数和文本应该与目录中的文件一样多。我获取目录中的所有文件并对其进行过滤。之后只计算和使用选定的一个。
现在我的问题是:
我想像 Excel 表格一样显示表格:它应该突出显示我的光标所在的单元格(在我的示例中它是一个上下移动的计数器)(目前我没有光标,所以我必须使用一个自创的“光标”。你会在程序中看到我的意思)。
我使用QStandardItemModel
来显示它,并使用QStandardItem
来定义它。
因为我想更改单元格的颜色,所以我使用QStandardItem
数组来一一保存单元格。
form.h:
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QTextTable>
#include <QFont>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QString>
#include <QStringList>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QBrush>
namespace Ui
class Form;
class Form : public QWidget
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
void my_setCFGFromDirectory();
void my_Highlighted(int, bool);
void my_loadCFG(int);
private:
Ui::Form *ui;
QFile file;
QTextStream textstream;
QDir directory;
QString filename;
QStringList stringlist;
QStringList filter;
QStandardItemModel *model;
QStandardItem *tableitem;
QStandardItem* pointerTableitem[];
int max_files;
int w_counter;
bool check1;
bool check2;
bool check3;
;
#endif // FORM_H
和 表单.cpp
#include "form.h"
#include "ui_form.h"
#include "rbobject.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
ui->setupUi(this);
Form::~Form()
delete ui;
void Form::my_Highlighted(int actual_count, bool modus)
if(modus == 1)
w_counter = 0;
while(w_counter < max_files)
if(w_counter == actual_count)
pointerTableitem[w_counter]->setBackground(QBrush(QColor(130,180,255)));
w_counter++;
else
w_counter = 0;
while(w_counter < max_files)
pointerTableitem[w_counter]->setBackground(QBrush(QColor(255,255,255)));
w_counter++;
void Form::my_setCFGFromDirectory()
directory.setPath("/etc/rosenbauer/CFG-Files");
filter << "*_CFG.ini";
stringlist = directory.entryList(filter); //takes the selected files and wriths them in a filelist
max_files = stringlist.count(); //Counts the selected files
pointerTableitem [max_files];
memset(pointerTableitem, 0, max_files*sizeof(int)); //The compiler can not see how many elements should be in the array at the time he constructs the array.
//So you have to use this to tell the compiler, how many elements it should create
model = new QStandardItemModel(max_files, 1, this); //Rows , Columns , this
model->setHorizontalHeaderItem(0, new QStandardItem(QString("CFG-Files"))); //Column , QStandarditem...name
for(w_counter = 0; w_counter != max_files; w_counter++)
tableitem = new QStandardItem();
tableitem->setBackground(QBrush(QColor(255,255,255)));
tableitem->setText(QString(stringlist[w_counter])); //Wriths text in the cell
qDebug() << tableitem->text();
pointerTableitem[w_counter] = tableitem; //Stacks the tableitems in a filelist
model->setItem(w_counter, 0, tableitem); //Row, Column , tableitem...text
w_counter = 0;
//pointerTableitem[2]->setBackground(QBrush(QColor(130,180,255))); //Test
ui->TableConfig->setModel(model); //Sets the table into the UI
void Form::my_loadCFG(int file_position)
check1 = 0;
check2 = 0;
directory.setPath("/etc/rosenbauer/etc/rosenbauer");
check1 = directory.remove("SA008_890560-001_CFG.ini");
check2 = directory.remove("reparsed/SA008_890560-001_CFG.ini_reparsed");
if(check1 && check2)
filename = pointerTableitem[file_position]->text();
check3 = QFile::copy("/etc/rosenbauer/CFG-Files/"+filename, "/etc/rosenbauer/SA008_890560-001_CFG.ini");
if(!check3)
qDebug() << "Error! Could not copy new CFG-file into directory";
else
qDebug() << "Error! Could not delete running CFG-file(s) from directory";
主头文件rbobject45000.h
#ifndef RbObject45000_H
#define RbObject45000_H
#include "rbobject.h"
#include "form.h"
class RbObject45000 : public RbObject
public:
RbObject45000();
RbObject45000(qint32 rbObjectId, RDataObject *dataobject, qint32 style, QObject *parent = 0);
RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent);
bool entered_ui;
bool entered_key;
short counter;
short w_count;
short delay_count;
short max_files;
short begin;
short end;
Form *f;
void exec();
~RbObject45000();
;
#endif // RbObject45000_H
这是主要的: rbobject45000.cpp
RbObject45000::RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent):
RbObject(rbObjectId, style, prio, parent)
entered_ui = 0;
entered_key = 0;
counter = 0;
w_count = 1; //... whilecounter
delay_count = 0; //... delay for the deadtime
max_files = 0;
begin = 0;
end = 0;
f= new Form(); //f...name of the displayed UI
void RbObject45000::exec()
//Opens the file on the display
if(getKey(RB_KEY_9) && getKey(RB_KEY_7) && entered_ui ==0)
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
// Prescind them file in the table
if(entered_ui == 1 && delay_count == 2)
if(getKey(RB_KEY_7))
counter--;
entered_key = 1;
if(counter < 0)
counter = 0;
else if(getKey(RB_KEY_9))
counter++;
entered_key = 1;
if(counter > max_files)
counter = max_files;
if(entered_key == 1)
while(w_count <= max_files)
f->my_Highlighted(w_count, 0); //Cell , not highlighted
w_count++;
w_count = 0;
f->my_Highlighted(counter,1); //Cell , highlighted
entered_key = 0;
delay_count = 0;
else if(delay_count == 2) //if delay == 2 and nobody hit a button
delay_count = 0;
delay_count++;
//Load the coosen file as programm-config in
if(entered_ui == 1)
if(getKey(RB_KEY_8))
f->my_loadCFG(counter);
(RB_KEY_7-9 是硬件模块的按钮,只需点击它们)
因此,如果我这样做,程序将编译并启动。如果我按下按钮并且程序运行到my_setCFGFromDirectory()
它会退出窗口并停止运行,但是如果在my_setCFGFromDirectory()
中声明了QStandardItem pointerTableitem
一切正常(但pointerTableitem
需要是private
)。
我得到的错误是:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Form(0x167498), parent's thread is QThread(0x1414e8), current thread is QThread(0x15d2d8)
Segmentation fault
似乎说我使用了一个线程(我确定我没有)。但我知道这与pointerTableitem
以及标头和cpp 中的声明有关。
【问题讨论】:
你说你没有使用线程,但RbObject45000::exec()
似乎很可能是一个覆盖QThread::exec()
的函数。你能发布RbObject4500
的定义吗?
我编辑了它 :) 但它在 45000 文件中没有任何问题。该文件工作正常。只有“form.h”和“form.cpp”是麻烦制造者
根据我能从中得到的答案发布了答案。而且您正在使用线程;)
【参考方案1】:
如果我没记错的话,问题就在这里:
model = new QStandardItemModel(max_files, 1, this);
您尝试创建一个 QStandardItemModel
传递您的 Form
实例 this
作为父级,表单是在主线程上创建的,此调用显然发生在另一个线程上(您所做的编辑还不够,它尚不清楚RbObject
是否继承QThread
但您可以自己检查)以及错误消息。
为什么不在主线程调用函数呢?而不是这样做
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
在不同的线程中,为Form
类创建一个槽/信号对,将此代码放入槽中并从RbObject45000::exec()
触发连接的信号。从非 UI trhead 进行 UI 操作是不正确的。
【讨论】:
1.是啊。我想你明白你想说的话。我会改的。非常感谢^^ :) 2. 嗯。所以你的意思是f->show()
funktion 在错误的文件中?如果是这样,我可以告诉你它是这样的,我无法改变它。我现在正在处理我最后一年的项目,而我正在与之合作的公司是这样说的。是的。就是这样:)
好吧,f->show()
不是主要问题(我不知道 Qt 内部结构,也许它会检查它是从哪个线程调用的,并且当您调用时,内部实际上会向主线程发出信号它来自非 gui 线程),f->my_setCFGFromDirectory()
是。您遇到的问题是因为您在错误的线程中创建了一个带有父级的对象。如果您可以 1) 将 my_setCFGFromDirectory()
中的所有内容移动到 Form
的插槽并为 my_setCFGFromDirectory()
中的该插槽发出信号,您应该没问题。
嗯。嗯。您是指my_setCFGFromDirectory
中的所有内容,还是仅声明声明内容?
一切,如果你只是把它的一部分放在插槽中,你认为它会如何工作?让我们这样说 - 创建一个新插槽 Form::my_setCFGFromDirectorySlot
,其中包含来自 Form::my_setCFGFromDirectory
的所有代码,为 Form
创建一个新信号,称为 my_SetCFGFromDirectorySignal
,将信号连接到插槽,然后在 @987654341 @ 只做emit my_SetCFGFromDirectorySignal();
而不是当前的逻辑。
嗯。不完全是我需要的,但它有效:) 非常感谢 :)以上是关于不使用线程的 C++/Qt 线程错误的主要内容,如果未能解决你的问题,请参考以下文章