当使用reflex-gi-gtk-0.2.0.0时,我可以从事件中访问动态:
submitButtonE4 <- eventOnSignal submitButton #clicked
(
do
let processDyn dynCompany = do
case dynCompany of
Just company -> do
path <- chartAnnualROA company fileOptions800x600 --generateChart company
Gtk.imageClear chartImage
Gtk.set chartImage [#file := T.pack defaultReportPath]
--return x -- path
case T.null $ T.pack path of
True -> return "" --dynCompany
Nothing -> return "" -- dynCompany
return $ ffor maybeCompanyDyn processDyn
>>= )但是为了进行评估,我需要将它绑定到一个标签:sink submitClickStatusLabel [#label :== ffor submitButtonE4 (T.pack . show)],它不能像在Dynamic (SpiderTimeline x) (IO (Maybe Company))中那样工作。
因此,我必须去获取动态绑定到的信息:
(
do
name <- Gtk.get companyCboxBoxEntryWidget #text
case Map.lookup name companyMap of
Just company -> do
path <- chartAnnualROA company fileOptions800x600 --generateChart company
Gtk.imageClear chartImage
Gtk.set chartImage [#file := T.pack defaultReportPath]
return path
Nothing -> return "../investingRIO/src/Data/Reports/initialChart.svg"
>>= )现在我可以将其下沉,并引起求值。
sink submitClickStatusLabel [#label :== ffor submitButtonE (T.pack . show)]
在使用第一种方法时,我找不到任何方法来强制评估。如何在不沉没到另一个小部件的情况下强制求值?
谢谢
发布于 2021-03-05 19:00:03
我认为您的大部分麻烦都来自于这样一个事实,即您想要在eventOnSignal中做大量的工作。这个地方并不打算做实际繁重的业务逻辑工作,它也不会为您提供适当的上下文来有效地使用响应值,例如您当前正在经历的Dynamic。
eventOnSignal*系列函数的实际用例是获取反应式网络的基本输入。按钮提供的输入不携带任何实际信息。它只是在按钮被点击时提供信息。对于这样的情况,您通常不想直接使用eventOnSignal,而是使用eventOnSignal0,所以让我们这样做:
submitClickedE <- eventOnSignal0 submitButton #clicked由此返回的类型为submitClickedE :: Event t ()。正如您所看到的,Event有一个()作为它的值,这正是我们想要的,因为仅仅单击按钮本身并不会产生任何值。但是您希望对processDyn中的值调用IO-producing函数,因此让我们首先构造要执行的IO操作:
let processDynD = processDyn <$> dynCompany这里的赋值类型为processDynD :: Dynamic t (IO (Maybe Company))。如您所见,IO尚未执行。幸运的是,reflex提供了一个在反应值内部执行IO操作的操作,称为performEvent :: Event t (Performable m a) -> m (Event t a)。关于这种类型,有两件事并不完全符合我们目前的需求。首先,它期望monad被执行为Performable m,而我们有IO,但我们稍后会谈到这一点。第二个也是更紧迫的问题是,performEvent期望的是Event,而不是Dynamic。这是有道理的,因为您不能连续地执行IO操作。您必须决定何时执行IO操作。
AIUI您希望在单击submitButton时执行IO。所以我们想要一个在submitClickedE触发时触发的Event,但它应该在processDynD内部触发当前值。这样做被称为“使用Event对Behavior进行采样”,可以使用操作符(<@)来完成。在本例中,您希望对Dynamic进行采样,但您始终可以使用current将Dynamic转换为Behavior。因此,要获得预期的Event,您可以使用以下命令:
let processDynE = current processDynD <@ submitClickedE赋值的值为processDynE :: Event t (IO (Maybe Company))。但是正如您所看到的,IO仍然没有被执行。我们现在可以使用前面讨论过的performEvent来实现这一点:
processedCompany <- performEvent $ runGtk <$> processDynE我们使用runGtk将processDynE中的IO提升到所需的Performable m。返回值的类型为processedCompany :: Event t (Maybe Company)。现在,您可以将其嵌入到您的输出标签中,这是您的初衷:
sink submitClickStatusLabel [#label :== T.pack . show <$> processedCompany]但请注意,与您最初的尝试不同,我们现在使用的是Event而不是Dynamic。如果您实际上需要所有这些内容的Dynamic,则必须使用holdDyn initialValue processedCompany从Event构造它。但是,您必须提供一个initialValue,否则在第一次单击Dynamic之前,submitButton就没有值了。
发布于 2021-03-05 22:45:13
这是基于Kritzefitz的答案的新版本。
从组合框中选择公司的事件,与前面相同
companySelectionE <- eventOnAttribute companyCboxBoxEntryWidget #text将动态替换为行为。
companySelectionB <- hold Nothing $ ffor companySelectionE (`Map.lookup` companyMap) generateChart (从processDyn重命名)返回一个()而不是FilePath,这是一种强制求值的尝试,现在由performEvent完成。
let
generateChart company = do
case company of
Just companyJ -> do
chartAnnualROA companyJ fileOptions800x600
Gtk.imageClear chartImage
Gtk.set chartImage [#file := T.pack defaultReportPath]
return ()
Nothing -> return () submitClickedE现在使用eventOnSignal0而不是eventOnSignal
submitClickedE <- eventOnSignal0 submitButton #clicked现在,从所选公司创建图表是一种行为,而不是动态行为。
let generateChartB = generateChart <$> companySelectionB现在,我使用<@从submit事件创建一个新事件并生成图表行为。
let generateChartE = generateChartB <@ submitClickedE 以及performEvent的使用,它消除了我创建和下沉到的所有标签,试图让我的IO进行评估。它还消除了从generateChart返回的FilePath,以及强制求值的尝试。
processedCompany <- performEvent $ runGtk <$> generateChartE谢谢为我理清了很多事情,谢谢。为了更容易阅读,这里用了一个引号:
companySelectionE <- eventOnAttribute companyCbox #text
companySelectionB <- hold Nothing $ ffor companySelectionE (`Map.lookup` companyMap)
let
generateChart company = do
case company of
Just companyJ -> do
chartAnnualROA companyJ fileOptions800x600
Gtk.set chartImage [#file := T.pack defaultReportPath]
return ()
Nothing -> return ()
submitClickedE <- eventOnSignal0 submitButton #clicked
let generateChartB = generateChart <$> companySelectionB
let generateChartE = generateChartB <@ submitClickedE
processedCompany <- performEvent $ runGtk <$> generateChartEhttps://stackoverflow.com/questions/66477914
复制相似问题