我在我的 PySide6 GUI 程序中添加了 LoadBar,但它似乎无限地持续下去

问题描述 投票:0回答:1

因此,我为某些任务添加了一个加载栏,但它会持续无限长时间,而无需使用它,我可以在 10 秒内获得结果。

这是我现在正在使用的加载栏类

class LoadingDialog(QDialog):
     def __init__(self):
        super().__init__()

        self.setWindowTitle("Working on your task")
        self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
        self.setFixedSize(300, 100)  # Fixed size dialog
    
        self.progress = QProgressBar(self)
        self.progress.setGeometry(30, 40, 240, 30)
        self.progress.setRange(0, 0)  # Indeterminate progress bar
    
        self.label = QLabel("Enumerating Please Wait...", self)
        self.label.setGeometry(110, 10, 80, 20)
    
        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.label)
        self.layout().addWidget(self.progress)
    
    def showEvent(self, event):
        super().showEvent(event)
        self.progress.setRange(0, 0)  # Start indeterminate progress
    
    def closeEvent(self, event):
        super().closeEvent(event)
        self.progress.setRange(0, 0)  # Reset progress on close

我在需要它的主要 GUI 功能中像这样使用它

        self.loading_dialog.exec()
    
        self.output_text.clear()
        self.output_text.append(f"Enumerating subdomains for {domain} using wordlist...\n")
    
        subdomains = self.subdomain_enum(domain, wordlist)
        if subdomains:
            self.display_subdomains("Wordlist", subdomains)
        else:
            self.output_text.append("No subdomains found.")
    
        self.loading_dialog.close()

这是需要 10 到 20 秒的功能,因为我提供的单词列表只有 10 或 12 个单词。

def subdomain_enum(self, domain, wordlist):
        output = []
        subdomains = []
        with open(wordlist, 'r') as file:
            subdomains = file.read().splitlines()
        
        for subdomain in subdomains:
            try:
                full_domain = f"{subdomain}.{domain}"
                result = dns.resolver.resolve(full_domain, 'A')
                for ipval in result:
                    output_line = f'{full_domain} | {ipval.to_text()}'
                    output.append(output_line)
            except Exception as e:
                pass

        return output

这是用于显示输出框是文本浏览器的结果

def display_subdomains(self, source, subdomains):
        self.output_text.append(f"From {source}:")
        if subdomains:
            for subdomain in subdomains:
                self.output_text.append(f"  - {subdomain}")
        else:
            self.output_text.append(f"  No subdomains found from {source}.")

现在我还没有尝试很多解决方案,因为我在网上没有看到与此相关的解决方案,因此需要帮助。谢谢你。

python user-interface pyqt loading pyside
1个回答
0
投票

请参阅有关

QDialog.exec()
的文档(强调我的):

将对话框显示为模式对话框,阻塞直到用户关闭它

这意味着在对话框关闭之前,该行之后的任何内容都不会被执行。

考虑使用

open()
函数:

将对话框显示为窗口模式对话框,立即返回

现在,即使使用

open()
将允许程序继续执行以下指令,问题是之后发生的事情可能会发生 阻塞,这意味着事件循环将无法执行任何操作,包括正确执行同时更新用户界面。

您可能最终会得到一个看起来冻结的空窗口,并且一旦其他函数返回,该窗口就会关闭。

在像这样的简单情况下,代码的阻塞部分中发生的事情基于相对“快速”的处理循环(每次迭代可能需要不到一秒),强制事件循环处理其通过调用

QApplication.processEvents()
:

进行事件
    def subdomain_enum(self, domain, wordlist):
        output = []
        subdomains = []
        with open(wordlist, 'r') as file:
            subdomains = file.read().splitlines()
        
        for subdomain in subdomains:
            QApplication.processEvents()
            ... # the rest of the code

但请注意,这只是基于有根据的猜测希望一切正常:

dns.resolver.resolve()
可能需要更多时间(可能是由于网络问题),结果可能仍然冻结用户界面直到收到回复或最终出现错误。

处理 I/O(包括网络访问)时,通常且强烈建议将逻辑移至单独的线程中。

请注意,UI 元素不是线程安全的,因此您必须不要尝试从另一个线程访问它们。唯一正确的方法是使用信号,可能是将“worker”逻辑移至 QThread。

我建议您对此事进行一些研究,并最终发布一个带有相关[mre]的问题,以防您无法使其按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.