QT Creator中的GUI项目在修补之后不工作

2024-05-14 21:59:41 发布

您现在位置:Python中文网/ 问答频道 /正文

把其他脚本的片段拼凑起来。我正在尝试为python脚本创建一个GUI(年度数据库)解密备份。此脚本需要密码、包含加密文件的文件夹的位置和写入加密文件的目标等参数。你知道吗

使用QT Creator制作了一个漂亮的gui,其中有一个按钮可以浏览到包含加密文件的文件夹。其路径显示在文本编辑字段中。 目的地也一样。 然后有一个字段输入已知密码。 最后有一个按钮来运行HHBD脚本,其中包含参数password、origin和destination location。你知道吗

由于我不知道哪里出了问题,调试器也不再给出错误,我需要一个程序员的眼睛来指出我的(许多)缺陷。你知道吗

感谢您查看下面的代码:

谷歌搜索了很多,但很多人发现解决方案都给出了错误,需要调试、查找和替换:-(

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDir>
#include <QString>
#include <QLabel>
#include <QProcess>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;

}

void MainWindow::on_pushButton_clicked()
{

    QString backup_dir = QFileDialog::getExistingDirectory(this,tr("Choose HiSuite Backup Folder"), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    ui->textEdit->setPlainText(backup_dir.replace('/','\\'));
}

void MainWindow::on_pushButton_2_clicked()
{

    QString destination_dir = QFileDialog::getExistingDirectory(this,tr("Choose Destination Folder"), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    ui->textEdit_2->setPlainText(destination_dir.replace('/','\\'));

}

void MainWindow::on_pushButton_3_clicked()
{
    QString passwordstring = ui->password->toPlainText();

    QProcess process;
    QString scriptFile =  QCoreApplication::applicationDirPath() + "./HHBD.py";

    QString pythonCommand = "python " + scriptFile +
                        " passwordstring" +
                        " backup_dir.replace('/','\\')" +
                        " destination_dir.replace('/','\\')";

    printf("PyCommand: %s\n", pythonCommand.toStdString().c_str());
    process.start (pythonCommand);

}

我想按“按钮3”脚本执行HHBD.py公司带有给定参数的脚本,如“pythonHHBD.py公司123456789 C:\test\C:\dest“其中“123456789”来自密码字段,“C:\test\”来自备份目录字段,“C:\dest”来自目标目录字段

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

你知道吗主窗口.ui你知道吗

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>395</width>
    <height>303</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Huawei HiSuite Backup Decrypter</string>
  </property>
  <property name="windowIcon">
   <iconset>
    <normaloff>J:/Downloads_2/huawei.png</normaloff>J:/Downloads_2/huawei.png</iconset>
  </property>
  <property name="autoFillBackground">
   <bool>true</bool>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>151</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Select HiSuite Backup Folder</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="textEdit">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>40</y>
      <width>381</width>
      <height>23</height>
     </rect>
    </property>
    <property name="sizePolicy">
     <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
      <horstretch>0</horstretch>
      <verstretch>0</verstretch>
     </sizepolicy>
    </property>
    <property name="verticalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOff</enum>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_2">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>70</y>
      <width>151</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Select Destination Folder</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="textEdit_2">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>100</y>
      <width>381</width>
      <height>21</height>
     </rect>
    </property>
    <property name="verticalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOff</enum>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>150</y>
      <width>381</width>
      <height>31</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>10</pointsize>
     </font>
    </property>
    <property name="autoFillBackground">
     <bool>true</bool>
    </property>
    <property name="lineWidth">
     <number>2</number>
    </property>
    <property name="text">
     <string>Type here the password given during the creation of the backup of the mobile device with Huawei HiSuite.</string>
    </property>
    <property name="wordWrap">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QTextEdit" name="password">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>190</y>
      <width>191</width>
      <height>21</height>
     </rect>
    </property>
    <property name="verticalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOff</enum>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_3">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>220</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>Decrypt HiSuite Backup</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>270</x>
      <y>170</y>
      <width>141</width>
      <height>111</height>
     </rect>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="pixmap">
     <pixmap>J:/Downloads_2/Aantekening 2019-10-24 141833.png</pixmap>
    </property>
   </widget>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Tags: namerect脚本uistringincludepropertywidget
1条回答
网友
1楼 · 发布于 2024-05-14 21:59:41

这是一个很小的程序,把它分散在三个文件中是没有意义的。你可以把它全部放在main.cpp。你知道吗

下面的例子是完整的和可编译的。整个文件有129行长。您可以从https://github.com/KubaO/stackoverflown/tree/master/questions/script-frontend-58555092下载完整的项目。你知道吗

看起来是这样的:

screenshot of the example application

首先,让我们从主窗口开始。您不需要使用QMainWindow,因为这是用于带有菜单等的“大”应用程序的。您只需要一个普通的QWidget

// https://github.com/KubaO/stackoverflown/tree/master/questions/script-frontend-58555092
#include <QtWidgets>
#include <initializer_list>

class MainWindow : public QWidget {
   Q_OBJECT

QProcess实例在窗口的生存期内保持不变,因此我们可以监视其状态和输出,而不是启动分离的进程:

   QProcess process;

UI非常简单,其元素可以很容易地作为成员提供:

   QGridLayout layout{this};
   QPushButton selectSource{tr("Select HiSuite Backup Folder")};
   QLineEdit source;
   QPushButton selectDestination{tr("Select Destination Folder")};
   QLineEdit destination;
   QLabel instruction{tr(
       "Type here the password given during the creation of "
       "the backup of the mobile device with Huawei HiSuite.")};
   QLineEdit password;
   QPushButton decrypt{tr("Decrypt HiSuite Backup")};
   QTextBrowser output;

   QFileSystemModel fsModel;
   QCompleter fsCompleter{&fsModel};

   QTextCharFormat statusFormat, commandFormat, stdoutFormat, stderrFormat;

   void setupUi();
   void doDecrypt();
   void onStateChanged(QProcess::ProcessState state);

  public:
   explicit MainWindow(QWidget *parent = nullptr);
};

请注意,所有用户可见的字符串都是用tr()包装的,这样就可以使用Qt语言学家轻松地进行翻译。你知道吗

用户界面的设置被排除在外,而且没有争议。路径输入字段有一个文件系统完成符,以便于手动输入路径。你知道吗

void MainWindow::setupUi() {
   setWindowTitle(tr("Huawei HiSuite Backup Decrypter"));
   QFont boldFont;
   boldFont.setBold(true);
   decrypt.setFont(boldFont);
   instruction.setWordWrap(true);

   commandFormat.setForeground(QColor(Qt::green).darker());
   statusFormat.setForeground(QColor(Qt::blue));
   stderrFormat.setForeground(QColor(Qt::red).darker());

   int row = 0;
   for (auto *widget : std::initializer_list<QWidget *>{
            &selectSource, &source, &selectDestination, &destination, &instruction,
            &password, &decrypt, &output}) {
      layout.addWidget(widget, row++, 0);
   }

   for (auto *button : {&selectSource, &selectDestination, &decrypt})
      button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);

   fsModel.setRootPath("");
   fsModel.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
   fsCompleter.setCompletionMode(QCompleter::PopupCompletion);
   source.setCompleter(&fsCompleter);
   destination.setCompleter(&fsCompleter);
}

大多数插槽非常小,可以在lambdas内部提供:

MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
   setupUi();

   connect(&selectSource, &QPushButton::clicked, [this] {
      auto dir = QFileDialog::getExistingDirectory(
          this, tr("Choose HiSuite Backup Folder"), QDir::homePath(),
          QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
      source.setText(dir);
   });

   connect(&selectDestination, &QPushButton::clicked, [this] {
      auto dir = QFileDialog::getExistingDirectory(
          this, tr("Choose Destination Folder"), QDir::homePath(),
          QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
      destination.setText(dir);
   });

   connect(&decrypt, &QPushButton::clicked, this, &MainWindow::doDecrypt);

   connect(&process, &QProcess::stateChanged, this, &MainWindow::onStateChanged);

该过程的输出显示在文本浏览器中,并着色以便于识别错误:

   connect(&process, &QProcess::readyReadStandardOutput, [this] {
      output.setCurrentCharFormat(stdoutFormat);
      output.append(process.readAllStandardOutput());
   });
   connect(&process, &QProcess::readyReadStandardError, [this] {
      output.setCurrentCharFormat(stderrFormat);
      output.append(process.readAllStandardError());
   });  
}

为了完整起见,指示过程的状态

void MainWindow::onStateChanged(QProcess::ProcessState state) {
   output.setCurrentCharFormat(statusFormat);
   switch (state) {
      case QProcess::Starting:
         output.append(tr("(starting)"));
         break;
      case QProcess::Running:
         output.append(tr("(started)"));
         break;
      case QProcess::NotRunning:
         output.append(tr("(not running)"));
         break;
   }
}

解密使用QProcessprogramarguments属性显式设置进程及其参数。这样就不会有路径中的空格等问题了-Qt会为我们处理所有的问题。请注意,applicationDirPath() + "./foo"有一个周期,它会给出类似于C:/path./foo的路径-这样的路径是无效的,周期不应该在那里。你知道吗

void MainWindow::doDecrypt() {
   output.clear();
   auto password = this->password.text();

   QString scriptFile = QCoreApplication::applicationDirPath() + "/HHBD.py";
   process.setProgram("python");
   process.setArguments({QDir::toNativeSeparators(scriptFile), password,
                         QDir::toNativeSeparators(source.text()),
                         QDir::toNativeSeparators(destination.text())});
   output.setCurrentCharFormat(commandFormat);
   output.setText(
       QStringLiteral("%1 %2").arg(process.program()).arg(process.arguments().join(' ')));
   process.start();
}

main函数显示窗口。moc文件包含在末尾,因为我们没有单独的main.h头文件:

int main(int argc, char *argv[]) {
   QApplication a(argc, argv);
   MainWindow w;
   w.show();
   return a.exec();
}
#include "main.moc"

这个例子到此结束。你知道吗

相关问题 更多 >

    热门问题