我试图将两个
SvgIcon
从MainView
传递到单独的Java类文件,它们是选项卡内容,所以我可以更改图标,但我找不到实现这样的功能的元素:
public SvgIcon getSvgIcon(String classSvgIcon) {
return (SvgIcon) CurrentInstance.get(SvgIcon.class).findAncestor(SvgIcon.class).hasClassName(classSvgIcon);
}
因为我认为它应该返回与元素中包含的类名相对应的
SvgIcon
元素,即使我更喜欢 ID,但我看到没有 hasIdAttribute()
函数,但它不起作用。 .
然后我尝试传递 MainView UI 类来直接访问我想要更改的组件,如下所示:
public static MainView getCurrent() {
return (MainView) CurrentInstance.get(UI.class);
}
但是即使在选项卡内容类中我现在可以调用
MainView.getCurrent().myIconElement
但是在函数中它说Cannot cast from UI to MainView
...应该如何正确重写该函数以便我可以访问我想要更改的svg图标?
提前感谢大家! 干杯!
[编辑]
我正在尝试实现更改图标的示例...
/* ************************************************************
* *
* MainView class *
* *
************************************************************ */
package com.myexample.application.views.main;
import java.util.HashMap;
import java.util.Map;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.NativeLabel;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.SvgIcon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.component.tabs.TabsVariant;
import com.vaadin.flow.internal.CurrentInstance;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.HighlightConditions;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouterLayout;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.flow.server.StreamResource;
@PageTitle("Main")
@Route("")
public class MainView extends VerticalLayout implements RouterLayout, BeforeEnterObserver {
private Map<Tab, RouterLink> tabSheets = new HashMap<>();
private Tabs mainTabs;
private HorizontalLayout toolbar;
private NativeLabel appname;
public SvgIcon iconToChange;
public MainView() {
RouteTabs tabsToAdd = new RouteTabs();
tabsToAdd.addTab(new RouterLink("Tab 1", MyTab1.class), VaadinIcon.EYE.create());
tabsToAdd.addTab(new RouterLink("Tab 2", MyTab2.class), VaadinIcon.EYE.create());
add(getToolbar(), tabsToAdd);
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
if (event.getNavigationTarget() == MainView.class) {
event.forwardTo(MyTab1.class);
}
}
public static MainView getCurrent() {
return (MainView) CurrentInstance.get(UI.class).getCurrent();
//return CurrentInstance.get(UI.class);
//return UI.getCurrent();
}
public SvgIcon getIconToChange() { return (SvgIcon) iconToChange; }
private HorizontalLayout getToolbar() {
HorizontalLayout leftLayout = new HorizontalLayout();
appname = new NativeLabel("My Test");
appname.setClassName("title-style");
leftLayout.add(appname);
leftLayout.setAlignItems(FlexComponent.Alignment.START);
leftLayout.setWidth("100%");
HorizontalLayout rightLayout = new HorizontalLayout();
StreamResource svgIconResource = new StreamResource("myOff_Icon.svg",
() -> getClass().getResourceAsStream("/img/myOff_Icon.svg"));
svgIconResource.setCacheTime(0);
iconToChange = new SvgIcon(svgIconResource);
iconToChange.addClassName("iconToChange");
iconToChange.setId("iconToChange");
iconToChange.setTooltipText("IconToChange");
rightLayout.add(iconToChange);
rightLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
rightLayout.setWidth("100%");
var toolbar = new HorizontalLayout(leftLayout, rightLayout);
toolbar.setWidthFull();
toolbar.addClassName("toolbar");
return toolbar;
}
private static class RouteTabs extends Tabs implements BeforeEnterObserver {
private final Map<RouterLink, Tab> routerLinkTabMap = new HashMap<>();
public void addTab(RouterLink routerLink, Icon iconToAdd) {
routerLink.setHighlightCondition(HighlightConditions.sameLocation());
routerLink.setHighlightAction(
(link, shouldHighlight) -> {
if (shouldHighlight) setSelectedTab(routerLinkTabMap.get(routerLink));
}
);
routerLinkTabMap.put(routerLink, new Tab(iconToAdd, routerLink));
add(routerLinkTabMap.get(routerLink));
this.addThemeVariants(TabsVariant.LUMO_EQUAL_WIDTH_TABS);
this.setMaxWidth("100%");
this.setWidthFull();
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
// In case no tabs will match
setSelectedTab(null);
}
}
/*public SvgIcon getSvgIcon(String idSvgIcon) {
//return (SvgIcon) CurrentInstance.get(SvgIcon.class).equals(getElement().getAttribute("id").equals(idSvgIcon));
//return (SvgIcon) CurrentInstance.get(SvgIcon.class).findAncestor(SvgIcon.class).hasClassName(idSvgIcon);
return (SvgIcon) CurrentInstance.get(SvgIcon.class).getElement().hasAttribute("id");
} */
}
/* ************************************************************
* *
* MainView class *
* *
************************************************************ */
/* ************************************************************
* *
* MyTab1.class class *
* *
************************************************************ */
package com.myexample.application.views.main;
import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.SvgIcon;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamResource;
@Route(value="mytab1", layout = MainView.class)
public class MyTab1 extends VerticalLayout {
/**
*
*/
private SvgIcon iconChangeTo;
private Text localText;
private Button localButton;
public ARDevices() {
localText = new Text("My Tab 1");
localButton = new Button("Change Icon");
localButton.addClickListener(e -> {
//iconChangeTo = Element.getAttribute("id").
//iconChangeTo = UI.getCurrent().navigate(SvgIcon.class).ifPresent(icon -> icon.hasClassName("iconToChange")).
//SvgIcon icon = ((MainView) MainView.getCurrent()).getIconToChange();
//MainView.getCurrent()
SvgIcon icon = MainView.getCurrent().getIconToChange()
//UIclass.iconToChange.setSrc( new StreamResource("myON_Icon.svg",
// () -> getClass().getResourceAsStream("/img/myON_Icon.svg")) );
});
add(localText, localButton);
}
}
/* ************************************************************
* *
* MyTab1.class class *
* *
************************************************************ */
我知道可以通过三种方法从子视图获取 MainView 实例。
第一个选项是获取当前 UI 实例并在其子级中找到 childView:
MainView mainView = (MainView) UI.getCurrent().getChildren()
.filter(component -> component.getClass() == MainView .class).findFirst().orElse(null);
第二个选项类似,但反之亦然,您从子视图开始向上看。它看起来更丑陋,因为你一次只能获取 1 个父级,而 getChildren 返回一个可过滤的流:
MainView mainView = null;
Optional<Component> parentOpt = this.getParent();
while(parentOpt.isPresent()) {
Component parent = parentOpt.get();
if(parent instanceof MainView) {
mainView = (MainView) parent;
parentOpt = Optional.empty(); // stop the loop
} else {
// look further
parentOpt = parent.getParent();
}
}
最后是第三个选项,这就是我使用的,但它需要依赖注入。在 MainView 以及所有可能需要它的子视图中,我们注入一个
MainViewBus
(不太确定命名。如果可以的话,为它找到一个更好的名称),我们可以使用它直接获取 MainView 。这里不需要 HTML 元素子/父爬行。
@Component
@UIScope
public class MainViewBus {
private MainView mainView;
public MainViewBus() {
}
public MainView getMainView() {
return this.mainView;
}
public void setMainView(MainView mainView) {
this.mainView = mainView;
}
}
public class MainView implements RouterLayout {
public MainView(MainViewBus mainViewBus){
mainViewBus.setMainView(this);
}
public void someMethod(){
Notification.show("You just invoked a method on MainView from a child view.");
}
}
@Route("foo", layout = MainView.class)
public class FooView extends VerticalLayout {
public FooView(MainViewBus mainViewBus){
add(new Button("Test MainView Bus", click -> mainViewBus.getMainView().someMethod()));
}
}