QWizard 中的异步验证

发布于 2024-10-14 06:14:05 字数 623 浏览 6 评论 0原文

我正在编写一个基于 QWizard Qt 对象的向导 UI。在一种特殊情况下,我希望用户使用主机、用户名和密码登录服务。然后,向导的其余部分操纵该服务来执行各种设置任务。登录可能需要一段时间,尤其是在 DNS 名称需要很长时间才能解析的错误情况下,或者甚至可能根本无法解析。

所以我的想法是使用 registerField 机制使所有三个字段成为强制性的,当用户点击“下一步”时,我们在向导页面上显示一个小提示“正在连接到服务器,请稍候...”,同时我们尝试在背景。如果连接成功,我们将进入下一页。如果没有,我们会突出显示有问题的字段并要求用户重试。

但是,我不知道如何实现这一点。我想到的选项:

1)覆盖 validatePage 并让它在后台启动一个线程。在 validatePage() 中输入等待,泵送 Qt 事件循环,直到线程完成。您可能认为这是最丑陋的解决方案,但是...

2) 隐藏真正的“下一步”按钮并添加一个自定义“下一步”按钮,单击该按钮时,会在线程中分派长时间运行的函数并等待“验证完成”信号被某物养大。当发生这种情况时,我们手动调用 QWizard::next() (并且我们完全绕过了来自 validatePage 和朋友的真正验证逻辑。)这甚至更丑陋,但将丑陋转移到了另一个级别,可能使开发更容易。

当然有更好的方法吗?

I'm writing a wizard UI based on the QWizard Qt object. There's one particular situation where I want the user to log in to a service using host, username, and password. The rest of the wizard then manipulates this service to do various setup tasks. The login may take a while, especially in error cases where the DNS name takes a long time to resolve -- or perhaps it may not even resolve at all.

So my idea is to make all three fields mandatory using the registerField mechanism, and when the user hits Next, we show a little throbber on the wizard page saying "Connecting to server, please wait..." while we try to connect in the background. If the connection succeeds, we advance to the next page. If not, we highlight the offending field and ask the user to try again.

However, I'm at a loss for how to accomplish this. The options I've thought of:

1) Override validatePage and have it start a thread in the background. Enter a wait inside validatePage() that pumps the Qt event loop until the thread finishes. You'd think this was the ugliest solution, but...

2) Hide the real Next button and add a custom Next button that, when clicked, dispatches my long running function in a thread and waits for a 'validation complete' signal to be raised by something. When that happens, we manually call QWizard::next() (and we completely bypass the real validation logic from validatePage and friends.) This is even uglier, but moves the ugliness to a different level that may make development easier.

Surely there's a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

有木有妳兜一样 2024-10-21 06:14:05

它在视觉上不那么吸引人,但您可以添加一个连接页面,然后移至该页面。如果连接成功,则在向导上调用 next(),如果连接失败,则调用 previous() 并突出显示相应的字段。它的优点是编码相对简单。

It's not as visually appealing, but you could add a connecting page, and move to that page. If the connection succeeds, call next() on the wizard, and if the connection fails, call previous() and highlight the appropriate fields. It has the advantage of being relatively straightforward to code.

ゃ懵逼小萝莉 2024-10-21 06:14:05

我的最终选择是#2(覆盖“下一步”按钮,模拟其行为,但手动捕获其单击事件并用它做我想做的事情。)编写胶水来定义“下一步”按钮的行为是最少的,我能够QWizardPage 的子类,带有许多钩子,使我可以在同一页面上运行我的任务,而不必切换到间隙页面并担心是否前进或后退。不过还是谢谢迦勒的回答。

My final choice was #2 (override the Next button, simulate its behavior, but capture its click events manually and do the things I want to with it.) Writing the glue to define the Next button's behavior was minimal, and I was able to subclass QWizardPage with a number of hooks that let me run my task ON the same page, instead of having to switch to an interstitial page and worry about whether to go forwards or backwards. Thanks Caleb for your answer though.

莫多说 2024-10-21 06:14:05

我知道这个问题已经得到解答(很久以前!),但以防万一其他人也遇到同样的挑战。另一种方法是创建一个 QLineEdit,将其初始化为空并将其设置为强制注册字段。这意味着“下一步”在填充一些文本之前不会启用。
正常运行连接任务,完成后使用 setText 将 QLineEdit 更新为“True”或“已登录”或除空以外的任何内容。这意味着内置的 isComplete 函数将被传递,因为之前缺少的必填字段现在已完成。如果您从未将其添加到布局中,那么它将不会被看到,并且用户将无法与其交互。

举个例子......

self.validated_field = QLineEdit("")
self.registerField('validated*', self.validated_field)

然后当您的登录过程成功完成时

self.validated_field.setText("True")

这应该可以完成并且非常轻量级。但请务必考虑用户随后返回该页面的情况以及是否需要将该字段重置为空白。如果是这种情况,那么只需添加 initialisePage() 函数将其设置回空白

self.validated_field.setText("")

考虑一下,您还可以将行编辑添加到显示中并禁用它,以便用户无法更新它,然后给它一个有意义的完成消息充当状态更新...

self.validated_field = QLineEdit("")
self.validated_field.setDisabled(True)
self.validated_field.setStyleSheet("border:0;background-color:none")
self.main_layout.addWidget(self.validated_field)
self.registerField('validated*', self.validated_field)

然后当您更新它时..

self.validated_field.setText("Logged in")

I know this has already been answered (a long time ago!) but in case anyone else is having the same challenge. Another method for this is to create a QLineEdit, initiate it as empty and set it as a mandatory registered field. This will mean that "Next" is not enabled until it is filled with some text.
Run your connection task as normal and when it completes use setText to update the QLineEdit to "True" or "Logged in" or anything other than empty. This will then mean the built in isComplete function will be passed as this previously missing mandatory field is now complete. If you never add it to the layout then it won't be seen and the user won't be able to interact with it.

As an example ...

self.validated_field = QLineEdit("")
self.registerField('validated*', self.validated_field)

and then when your login process completes successfully

self.validated_field.setText("True")

This should do it and is very lightweight. Be sure though that you consider the scenario where a user then goes back to that page and whether you need to reset the field to blank. If that's the case then just add in the initialisePage() function to set it back to blank

self.validated_field.setText("")

Thinking about it you could also add the line edit to the display and disable it so that a user cannot update it and then give it a meaningful completion message to act as a status update...

self.validated_field = QLineEdit("")
self.validated_field.setDisabled(True)
self.validated_field.setStyleSheet("border:0;background-color:none")
self.main_layout.addWidget(self.validated_field)
self.registerField('validated*', self.validated_field)

and then when you update it..

self.validated_field.setText("Logged in")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文