如何在哈希表中执行存储为引用的Tk-Canvas函数?

时间:2016-06-12 11:50:23

标签: perl reference tk

我正在尝试执行存储为哈希表中函数的引用的Tk函数。在下面的简化示例中,代码应绘制一个大的红点(即执行第14行)。我不能对createOval()做出有效的引用,也不能使用$ w->在哈希表中,也没有向下移动到第13行。我已经google了这个高低,但无济于事。我错过了什么?

如果我将$ w-> ...视为参考,则错误消息是“错误的args数量:...”,如果我填充\&在第10行的$ w前面:“不是a11.pl第9行的CODE引用。”

在Python中这很容易做到:只需将w.create_oval填入字典即可。

use strict;
use warnings;
use Tk;

my $mw = MainWindow->new;
my $w = $mw->Canvas(-width => 1200, -height => 800);
$w->pack;

my %xfun = (
    'b' => $w->createOval
);

$xfun{'b'}(200, 200, 250, 250, -fill=>'red');
#$w->createOval(200, 200, 250, 250, -fill=>'red');

MainLoop;

2 个答案:

答案 0 :(得分:3)

  

如果我将$ w-> ...视为参考,则错误消息为"错误的参数数量:..."

我不知道你的意思"作为参考"。

您的代码没有按照书面形式工作,因为<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <context:component-scan base-package="pl.spring.demo.entity" /> <jpa:repositories base-package="pl.spring.demo.repository" /> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!--<util:properties id="hsqldbJpaProps"location="classpath:/test_data_access/hsqldb_jpa.properties" /> --> <!--<jdbc:embedded-database id="dataSource" type="HSQL" /> --> <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/gielda" /> <property name="username" value="root" /> <property name="password" value="starterkit" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="packagesToScan" value="pl.spring.demo.entity" /> <property name="dataSource" ref="dataSource" /> <property name="jpaProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> </props> </property> <property name="persistenceProvider"> <bean class="org.hibernate.jpa.HibernatePersistenceProvider"> </bean> </property> </bean> </beans> 是一个没有参数的方法调用,与$w->createOval相同。

使用$w->createOval()解析为\&$w->createOval,其中(大部分)与\((&$w)->createOval)相同:

  • \($w->(@_)->createOval)视为代码引用,并使用当前参数列表$w调用它(这是您的错误发生的地方,因为@_实际上是一个对象)
  • 获取返回值并在其上调用$w方法
  • 引用createOval
  • 的返回值

您可以使用$w->can('createOval')获取对createOval子的引用,但这对您没有帮助,因为它只是函数(没有对象)。要调用它,您必须显式传入createOval作为第一个参数(这在方法调用中隐式发生):

$w

最直接的解决方案是my %xfun = ( 'b' => $w->can('createOval'), ); $xfun{'b'}($w, 200, 200, 250, 250, -fill=>'red'); ,即将方法调用包装在转发其参数的代理子中。

答案 1 :(得分:2)

以下似乎有效:

use strict;
use warnings;

use Tk;

my $mw = MainWindow->new;
my $w = $mw->Canvas(-width => 1200, -height => 800);
$w->pack;

my %xfun = (
    b => sub { $w->createOval(@_); },
);

$xfun{b}->(200, 200, 250, 250, -fill=>'red');

MainLoop;

注意:

我认为你的原始电话是:

$xfun{'b'}(200, 200, 250, 250, -fill=>'red');

没有用,因为它错过了第一个arg对象$w,但是当我失败时 尝试明确地传递$w作为第一个参数:

$xfun{'b'}($w, 200, 200, 250, 250, -fill=>'red');

它仍然无效..我收到了错误:

wrong # args: should be ".canvas create oval coords ?arg arg ...?"