504 lines
16 KiB
C++
504 lines
16 KiB
C++
#include "TwoMotorControl.h"
|
||
|
||
TwoMotorControl::TwoMotorControl(QWidget* parent) : QDialog(parent)
|
||
{
|
||
ui.setupUi(this);
|
||
|
||
ui.recordLine_tableWidget->setFocusPolicy(Qt::NoFocus);
|
||
|
||
ui.recordLine_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选择行为,以行为单位
|
||
//ui.recordLine_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);//设置选择模式,选择单行
|
||
//QHeaderView* headerView = ui.recordLine_tableWidget->verticalHeader();
|
||
//headerView->setHidden(true);//去除左边默认自带序列号
|
||
|
||
connect(this->ui.connect_btn, SIGNAL(pressed()), this, SLOT(onConnectMotor()));
|
||
|
||
connect(ui.addRecordLine_btn, SIGNAL(clicked()), this, SLOT(onAddRecordLine_btn()));
|
||
connect(ui.removeRecordLine_btn, SIGNAL(clicked()), this, SLOT(onRemoveRecordLine_btn()));
|
||
connect(ui.deleteRecordLine_btn, SIGNAL(clicked()), this, SLOT(onDeleteRecordLine_btn()));
|
||
connect(ui.saveRecordLine2File_btn, SIGNAL(clicked()), this, SLOT(onSaveRecordLine2File_btn()));
|
||
connect(ui.readRecordLineFile_btn, SIGNAL(clicked()), this, SLOT(onReadRecordLineFile_btn()));
|
||
}
|
||
|
||
void TwoMotorControl::setImager(ImagerOperationBase* imager)
|
||
{
|
||
m_Imager = imager;
|
||
}
|
||
|
||
void TwoMotorControl::setPosFileName(QString posFileName)
|
||
{
|
||
isWritePosFile = true;
|
||
m_posFileName = posFileName;
|
||
m_posFileHandle = fopen(posFileName.toStdString().c_str(), "w+");
|
||
}
|
||
|
||
bool TwoMotorControl::getState()
|
||
{
|
||
QEventLoop loop;
|
||
bool tmp = false;
|
||
bool received = false;
|
||
|
||
QTimer timer;
|
||
timer.setSingleShot(true);
|
||
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||
|
||
QMetaObject::Connection conn = QObject::connect(
|
||
m_coordinator, &TwoMotionCaptureCoordinator::recordState,
|
||
[&](bool state) {
|
||
tmp = state;
|
||
received = true;
|
||
loop.quit();
|
||
});
|
||
|
||
QMetaObject::invokeMethod(m_coordinator, "getRecordState", Qt::QueuedConnection);
|
||
timer.start(3000);
|
||
|
||
loop.exec();
|
||
|
||
disconnect(conn);
|
||
|
||
return tmp;
|
||
}
|
||
|
||
void TwoMotorControl::record_dark()
|
||
{
|
||
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
if (m_darkCaptureCoordinator == nullptr)
|
||
{
|
||
m_darkCaptureCoordinator = new DarkAndWhiteCaptureCoordinator(0, m_multiAxisController, m_Imager);
|
||
}
|
||
|
||
m_darkCaptureCoordinator->startStepMotion(s);
|
||
}
|
||
|
||
void TwoMotorControl::record_white()
|
||
{
|
||
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
if (m_whiteCaptureCoordinator == nullptr)
|
||
{
|
||
m_whiteCaptureCoordinator = new DarkAndWhiteCaptureCoordinator(1, m_multiAxisController, m_Imager);
|
||
}
|
||
|
||
m_whiteCaptureCoordinator->startStepMotion(s);
|
||
}
|
||
|
||
void TwoMotorControl::run()
|
||
{
|
||
if (m_coordinator==nullptr)
|
||
{
|
||
qRegisterMetaType<QVector<PathLine>>("QVector<PathLine>");
|
||
m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController, m_Imager);
|
||
m_coordinator->moveToThread(&m_coordinatorThread);
|
||
connect(&m_coordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater()));
|
||
connect(this, SIGNAL(start(QVector<PathLine>)), m_coordinator, SLOT(start(QVector<PathLine>)));
|
||
connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop()));
|
||
connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int)));
|
||
connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(int)));
|
||
connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete()));
|
||
m_coordinatorThread.start();
|
||
}
|
||
|
||
if (getState())
|
||
{
|
||
//std::cout << "已经开始运行,请勿重复点击!!!!!!!!" << std::endl;
|
||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("已经开始运行,请勿重复点击!!!!!!!!!"));
|
||
return;
|
||
}
|
||
|
||
QVector<PathLine> pathLines;
|
||
int rowCount = ui.recordLine_tableWidget->rowCount();
|
||
//int columnCount = ui.recordLine_tableWidget->columnCount();
|
||
for (size_t i = 0; i < rowCount; i++)
|
||
{
|
||
PathLine tmp;
|
||
|
||
tmp.targetYPosition = ui.recordLine_tableWidget->item(i, 0)->text().toDouble();
|
||
tmp.speedTargetYPosition = ui.recordLine_tableWidget->item(i, 1)->text().toDouble();
|
||
tmp.targetXMinPosition = ui.recordLine_tableWidget->item(i, 2)->text().toDouble();
|
||
tmp.speedTargetXMinPosition = ui.recordLine_tableWidget->item(i, 3)->text().toDouble();
|
||
tmp.targetXMaxPosition = ui.recordLine_tableWidget->item(i, 4)->text().toDouble();
|
||
tmp.speedTargetXMaxPosition = ui.recordLine_tableWidget->item(i, 5)->text().toDouble();
|
||
|
||
pathLines.append(tmp);
|
||
}
|
||
|
||
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
|
||
{
|
||
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
|
||
{
|
||
ui.recordLine_tableWidget->item(i, j)->setBackgroundColor(QColor(240, 240, 240));
|
||
}
|
||
}
|
||
|
||
emit start(pathLines);
|
||
}
|
||
|
||
void TwoMotorControl::stop()
|
||
{
|
||
emit stopSignal();
|
||
}
|
||
|
||
TwoMotorControl::~TwoMotorControl()
|
||
{
|
||
m_motorThread.quit();
|
||
m_motorThread.wait();
|
||
|
||
m_coordinatorThread.quit();
|
||
m_coordinatorThread.wait();
|
||
}
|
||
|
||
void TwoMotorControl::onConnectMotor()
|
||
{
|
||
try
|
||
{
|
||
FileOperation* fileOperation = new FileOperation();
|
||
string directory = fileOperation->getDirectoryOfExe();
|
||
QString configFilePath = QString::fromStdString(directory) + "\\twoMotorConfigFile.cfg";
|
||
|
||
m_multiAxisController = new IrisMultiMotorController(configFilePath);
|
||
}
|
||
catch (std::exception const& e)
|
||
{
|
||
QMessageBox msgBox;
|
||
msgBox.setText(QString::fromLocal8Bit("请连接马达!"));
|
||
msgBox.exec();
|
||
}
|
||
|
||
m_multiAxisController->moveToThread(&m_motorThread);
|
||
connect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater()));
|
||
|
||
connect(this->ui.xmotor_right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight()));
|
||
connect(this->ui.xmotor_right_btn, SIGNAL(released()), this, SLOT(onxMotorStop()));
|
||
connect(this->ui.xmotor_left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft()));
|
||
connect(this->ui.xmotor_left_btn, SIGNAL(released()), this, SLOT(onxMotorStop()));
|
||
|
||
connect(this->ui.ymotor_forward_btn, SIGNAL(pressed()), this, SLOT(onyMotorforward()));
|
||
connect(this->ui.ymotor_forward_btn, SIGNAL(released()), this, SLOT(onyMotorStop()));
|
||
connect(this->ui.ymotor_backward_btn, SIGNAL(pressed()), this, SLOT(onyMotorbackward()));
|
||
connect(this->ui.ymotor_backward_btn, SIGNAL(released()), this, SLOT(onyMotorStop()));
|
||
|
||
connect(this->ui.move2loc_x_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc()));
|
||
connect(this->ui.move2loc_y_pushButton, SIGNAL(pressed()), this, SLOT(onyMove2Loc()));
|
||
|
||
connect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector<double>)), this, SLOT(displayRealTimeLoc(std::vector<double>)));
|
||
|
||
connect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int)));
|
||
connect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int)));
|
||
connect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int)));
|
||
|
||
connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart()));
|
||
connect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int)));
|
||
|
||
connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(on_rangeMeasurement()));
|
||
connect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int)));
|
||
|
||
connect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int)));
|
||
connect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector<int>)), this, SLOT(display_motors_connectivity(std::vector<int>)));
|
||
|
||
m_motorThread.start();
|
||
emit testConnectivitySignal(0, 1000);
|
||
emit testConnectivitySignal(1, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::receiveStartRecordLineNum(int lineNum)
|
||
{
|
||
emit startLineNumSignal(lineNum);
|
||
for (size_t i = 0; i < ui.recordLine_tableWidget->columnCount(); i++)
|
||
{
|
||
ui.recordLine_tableWidget->item(lineNum, i)->setBackgroundColor(QColor(255, 0, 0));
|
||
}
|
||
}
|
||
|
||
void TwoMotorControl::receiveFinishRecordLineNum(int lineNum)
|
||
{
|
||
for (size_t i = 0; i < ui.recordLine_tableWidget->columnCount(); i++)
|
||
{
|
||
ui.recordLine_tableWidget->item(lineNum, i)->setBackgroundColor(QColor(0, 255, 0));
|
||
}
|
||
}
|
||
|
||
void TwoMotorControl::onSequenceComplete()
|
||
{
|
||
isWritePosFile = false;
|
||
fclose(m_posFileHandle);
|
||
|
||
emit sequenceComplete();
|
||
}
|
||
|
||
void TwoMotorControl::display_motors_connectivity(std::vector<int> connectivity)
|
||
{
|
||
//std::cout << "-----------------------------------"<<connectivity.size()<< std::endl;
|
||
if (connectivity[0])
|
||
{
|
||
this->ui.xMotorStateLabel->setStyleSheet("QLabel{background-color:rgb(0,255,0);}");
|
||
}
|
||
else
|
||
{
|
||
this->ui.xMotorStateLabel->setStyleSheet("QLabel{background-color:rgb(255,0,0);}");
|
||
}
|
||
|
||
if (connectivity[1])
|
||
{
|
||
this->ui.yMotorStateLabel->setStyleSheet("QLabel{background-color:rgb(0,255,0);}");
|
||
}
|
||
else
|
||
{
|
||
this->ui.yMotorStateLabel->setStyleSheet("QLabel{background-color:rgb(255,0,0);}");
|
||
}
|
||
}
|
||
|
||
void TwoMotorControl::onxMotorRight()
|
||
{
|
||
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
emit moveSignal(0, false, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onxMotorLeft()
|
||
{
|
||
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
emit moveSignal(0, true, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onxMotorStop()
|
||
{
|
||
emit stopSignal(0);
|
||
}
|
||
|
||
void TwoMotorControl::onyMotorforward()
|
||
{
|
||
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
emit moveSignal(1, false, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onyMotorbackward()
|
||
{
|
||
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
|
||
|
||
emit moveSignal(1, true, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onyMotorStop()
|
||
{
|
||
emit stopSignal(1);
|
||
}
|
||
|
||
void TwoMotorControl::onxMove2Loc()
|
||
{
|
||
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
double l = ui.move2loc_x_lineEdit->text().toDouble();
|
||
|
||
emit move2LocSignal(0, l, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onyMove2Loc()
|
||
{
|
||
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
|
||
double l = ui.move2loc_y_lineEdit->text().toDouble();
|
||
|
||
emit move2LocSignal(1, l, s, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::displayRealTimeLoc(std::vector<double> loc)
|
||
{
|
||
double tmp = round(loc[0] * 100) / 100;
|
||
if (isWritePosFile)
|
||
{
|
||
long long timeOs = getNanosecondsSinceMidnight();
|
||
fprintf(m_posFileHandle, "%lld,%f\n", timeOs, loc[0]);
|
||
}
|
||
this->ui.xmotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
|
||
|
||
tmp = round(loc[1] * 100) / 100;
|
||
this->ui.ymotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
|
||
|
||
emit broadcastLocationSignal(loc);
|
||
}
|
||
|
||
void TwoMotorControl::zeroStart()
|
||
{
|
||
zeroStartSignal(0);
|
||
zeroStartSignal(1);
|
||
}
|
||
|
||
void TwoMotorControl::on_rangeMeasurement()
|
||
{
|
||
double s0 = ui.xmotor_move_speed_lineEdit->text().toDouble();
|
||
emit rangeMeasurement(0, s0, 1000);
|
||
|
||
s0 = ui.ymotor_move_speed_lineEdit->text().toDouble();
|
||
emit rangeMeasurement(1, s0, 1000);
|
||
}
|
||
|
||
void TwoMotorControl::onAddRecordLine_btn()
|
||
{
|
||
//准备数据:获取y马达的当前位置,获取x马达的当前位置和最大位置
|
||
double currentPosOfYmotor = 15;
|
||
|
||
double currentPosOfXmotor = 0;
|
||
double maxRangeOfXmotor = 50;
|
||
|
||
//获取选中行的索引
|
||
int currentRow = ui.recordLine_tableWidget->currentRow();
|
||
std::cout << "currentRow:" << currentRow << std::endl;
|
||
|
||
QTableWidgetItem* Item1 = new QTableWidgetItem(QString::number(currentPosOfYmotor, 10, 2));
|
||
QTableWidgetItem* Item2 = new QTableWidgetItem(QString::number(1, 10, 2));
|
||
QTableWidgetItem* Item3 = new QTableWidgetItem(QString::number(currentPosOfXmotor, 10, 2));
|
||
QTableWidgetItem* Item4 = new QTableWidgetItem(QString::number(1, 10, 2));
|
||
QTableWidgetItem* Item5 = new QTableWidgetItem(QString::number(maxRangeOfXmotor, 10, 2));
|
||
QTableWidgetItem* Item6 = new QTableWidgetItem(QString::number(1, 10, 2));
|
||
Item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
Item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
Item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
Item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
Item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
Item6->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
if (currentRow == -1)//当没有选中行时
|
||
{
|
||
int RowCount = ui.recordLine_tableWidget->rowCount();//Returns the number of rows. 从1开始的
|
||
ui.recordLine_tableWidget->insertRow(RowCount);//增加一行,形参是从0开始的
|
||
|
||
ui.recordLine_tableWidget->setItem(RowCount, 0, Item1);
|
||
ui.recordLine_tableWidget->setItem(RowCount, 1, Item2);
|
||
ui.recordLine_tableWidget->setItem(RowCount, 2, Item3);
|
||
ui.recordLine_tableWidget->setItem(RowCount, 3, Item4);
|
||
ui.recordLine_tableWidget->setItem(RowCount, 4, Item5);
|
||
ui.recordLine_tableWidget->setItem(RowCount, 5, Item6);
|
||
}
|
||
else
|
||
{
|
||
ui.recordLine_tableWidget->insertRow(currentRow + 1);//增加一行,形参是从0开始的
|
||
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 0, Item1);
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 1, Item2);
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 2, Item3);
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 3, Item4);
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 4, Item5);
|
||
ui.recordLine_tableWidget->setItem(currentRow + 1, 5, Item6);
|
||
}
|
||
}
|
||
|
||
void TwoMotorControl::onRemoveRecordLine_btn()
|
||
{
|
||
int rowIndex = ui.recordLine_tableWidget->currentRow();
|
||
if (rowIndex != -1)
|
||
ui.recordLine_tableWidget->removeRow(rowIndex);
|
||
}
|
||
|
||
void TwoMotorControl::onDeleteRecordLine_btn()
|
||
{
|
||
int rowCount = ui.recordLine_tableWidget->rowCount();
|
||
for (size_t i = 0; i < rowCount; i++)
|
||
{
|
||
ui.recordLine_tableWidget->removeRow(0);
|
||
}
|
||
}
|
||
|
||
void TwoMotorControl::onSaveRecordLine2File_btn()
|
||
{
|
||
//确保采集线存在
|
||
if (ui.recordLine_tableWidget->rowCount() <= 0)
|
||
{
|
||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先生成轨迹!"));
|
||
return;
|
||
}
|
||
|
||
FileOperation* fileOperation = new FileOperation();
|
||
string directory = fileOperation->getDirectoryOfExe();
|
||
|
||
QString RecordLineFilePath = QFileDialog::getSaveFileName(this, tr("Save RecordLine3 File"),
|
||
QString::fromStdString(directory),
|
||
tr("RecordLineFile3 (*.RecordLine3)"));
|
||
|
||
if (RecordLineFilePath.isEmpty())
|
||
{
|
||
return;
|
||
}
|
||
|
||
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "wb+");
|
||
|
||
double number = ui.recordLine_tableWidget->rowCount() * ui.recordLine_tableWidget->columnCount();
|
||
fwrite(&number, sizeof(double), 1, RecordLineFileHandle);
|
||
|
||
double* data = new double[number];
|
||
//double data[number];
|
||
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
|
||
{
|
||
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
|
||
{
|
||
data[i * ui.recordLine_tableWidget->columnCount() + j] = ui.recordLine_tableWidget->item(i, j)->text().toDouble();
|
||
}
|
||
}
|
||
|
||
fwrite(data, sizeof(double), number, RecordLineFileHandle);
|
||
|
||
fclose(RecordLineFileHandle);
|
||
delete[] data;
|
||
|
||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("保存成功!"));
|
||
}
|
||
|
||
void TwoMotorControl::onReadRecordLineFile_btn()
|
||
{
|
||
//打开文件
|
||
FileOperation* fileOperation = new FileOperation();
|
||
string directory = fileOperation->getDirectoryOfExe();
|
||
|
||
QString RecordLineFilePath = QFileDialog::getOpenFileName(this, tr("Open RecordLine3 File"),
|
||
QString::fromStdString(directory),
|
||
tr("RecordLineFile (*.RecordLine3)"));
|
||
|
||
if (RecordLineFilePath.isEmpty())
|
||
{
|
||
return;
|
||
}
|
||
|
||
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb");
|
||
double number;
|
||
|
||
//读取数据
|
||
fread(&number, sizeof(double), 1, RecordLineFileHandle);
|
||
|
||
double* data = new double[number];
|
||
for (size_t i = 0; i < number; i++)
|
||
{
|
||
fread(data + i, sizeof(double), 1, RecordLineFileHandle);
|
||
//std::cout << *(data + i) << std::endl;
|
||
}
|
||
|
||
//向tableWidget添加采集线
|
||
//(1)去掉tableWidget中所有的行
|
||
int rowCount = ui.recordLine_tableWidget->rowCount();
|
||
for (size_t i = 0; i < rowCount; i++)
|
||
{
|
||
ui.recordLine_tableWidget->removeRow(0);
|
||
}
|
||
//(2)添加行(采集线)
|
||
int RecordLineCount = number / ui.recordLine_tableWidget->columnCount();
|
||
for (size_t i = 0; i < RecordLineCount; i++)
|
||
{
|
||
ui.recordLine_tableWidget->insertRow(0);
|
||
|
||
}
|
||
//(3)向tableWidget填充数据
|
||
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
|
||
{
|
||
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
|
||
{
|
||
QTableWidgetItem* tmp = new QTableWidgetItem(QString::number(data[i * ui.recordLine_tableWidget->columnCount() + j], 10, 5));
|
||
tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||
ui.recordLine_tableWidget->setItem(i, j, tmp);
|
||
}
|
||
}
|
||
|
||
fclose(RecordLineFileHandle);
|
||
delete[] data;
|
||
|
||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("读取成功!"));
|
||
}
|