小程序richtext_用于基于SWT的应用程序的RichText编辑器组件

小程序richtext

本文将完成使用SWT实现我们自己的RichText编辑器组件的任务。 在为我的一位客户开发基于桌面的应用程序时,我遇到了这样的可视化组件的需求,并希望添加一项功能,以允许用户使用粗体,斜体,删除线等功能来写富文本注释。 那时,我开始研究网络,以找到一个开放源代码库,该库可以使我免于从头开始部署它的工作,而我遇到了“已完成”实现的列表 。
让我们在这里列出我对这种组件的需求:
  • 它应该是本地SWT组件,而不是Eclipse View或Editor,并且必须可嵌入任何SWT组合中。
  • 它应允许使用粗体,斜体,删除线等基本格式。
  • 它应该支持剪贴板的基本操作,例如复制,剪切和粘贴。
  • 它应该使用基本HTML输出文本。
  • 它需要能够解析所生成的基本HTML,以允许版本。
因此,我发现的大多数解决方案都不符合我的需求,因为它们要么是Eclipse Views / Editor,要么太笨拙,无法集成,要么试图实现太多功能,要么与我用来为自己的公司打上烙印的图标集不符应用程序(尽管这是一个小问题,但总结起来,这为我做出决定提供了更多原因)。 因此,最后我终于决定根据StyledText SWT标准组件从头开始编写它,并以该示例为起点。
RichText控件
几乎所有的工作都将由RichText控件本身执行。 我将添加一些支持类,这些支持类将用作将结果文本格式化为基本HTML的助手,以及图像,本地化字符串等的提供者。
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;import javax.xml.parsers.ParserConfigurationException;import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CaretListener;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Caret;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.xml.sax.SAXException;public class RichText extends Composite {private List cachedStyles =Collections.synchronizedList(new LinkedList());private ToolBar toolBar;private StyledText styledText;private ToolItem boldBtn;private ToolItem italicBtn;private ToolItem strikeThroughBtn;private ToolItem underlineBtn;private ToolItem pasteBtn;private ToolItem eraserBtn;public RichText(Composite parent, int style) {super(parent, style);initComponents();}public void addCaretListener(CaretListener listener) {styledText.addCaretListener(listener);}public void removeCaretListener(CaretListener listener) {styledText.removeCaretListener(listener);}public void addExtendedModifyListener(ExtendedModifyListener listener) {styledText.addExtendedModifyListener(listener);}public void removeExtendedModifyListener(ExtendedModifyListener listener) {styledText.removeExtendedModifyListener(listener);}public void addModifyListener(ModifyListener listener) {styledText.addModifyListener(listener);}public void removeModifyListener(ModifyListener listener) {styledText.removeModifyListener(listener);}public void addVerifyKeyListener(VerifyKeyListener listener) {styledText.addVerifyKeyListener(listener);}public void removeVerifyKeyListener(VerifyKeyListener listener) {styledText.removeVerifyKeyListener(listener);}public void addVerifyListener(VerifyListener listener) {styledText.addVerifyListener(listener);}public void removeVerifyListener(VerifyListener listener) {styledText.removeVerifyListener(listener);}public int getCharCount() {return styledText.getCharCount();}public Caret getCaret() {return styledText.getCaret();}public int getCaretOffset() {return styledText.getCaretOffset();}/*** Obtain an HTML formatted text from the component contents** @return an HTML formatted text*/public String getFormattedText() {String plainText = styledText.getText();RichStringBuilder builder = new RichStringBuilder();Integer[] lineBreaks = getLineBreaks();int brIdx = 0;int start = 0;int end = (lineBreaks.length > brIdx ? lineBreaks[brIdx++] : plainText.length() - 1);while (start < end) {builder.startParagraph();StyleRange[] ranges = styledText.getStyleRanges(start, (end - start));if (ranges != null && ranges.length > 0) {for (int i = 0;i < ranges.length;i++) {if (start < ranges[i].start) {builder.append(plainText.substring(start, ranges[i].start));}List styles = translateStyle(ranges[i]);builder.startFontStyles(styles.toArray(new FontStyle[styles.size()]));builder.append(plainText.substring(ranges[i].start,ranges[i].start + ranges[i].length));builder.endFontStyles(styles.size());start = (ranges[i].start + ranges[i].length) + 1;}}if (start < end) {builder.append(plainText.substring(start, end));}start = end + styledText.getLineDelimiter().length();end = (lineBreaks.length > brIdx ? lineBreaks[brIdx++] : plainText.length() - 1);builder.endParagraph();}return builder.toString();}public void setFormattedText(String text)throws ParserConfigurationException, SAXException, IOException {RichTextParser parser = RichTextParser.parse(text);styledText.setText(parser.getText());styledText.setStyleRanges(parser.getStyleRanges());}public int getLineAtOffset(int offset) {return styledText.getLineAtOffset(offset);}public int getLineCount() {return styledText.getLineCount();}public int getLineSpacing() {return styledText.getLineSpacing();}public String getText() {return styledText.getText();}protected void applyFontStyleToSelection(FontStyle style) {Point sel = styledText.getSelectionRange();if ((sel == null) || (sel.y == 0)) {return ;}StyleRange newStyle;for (int i = sel.x; i < (sel.x + sel.y); i++) {StyleRange range = styledText.getStyleRangeAtOffset(i);if (range != null) {newStyle = (StyleRange) range.clone();newStyle.start = i;newStyle.length = 1;} else {newStyle = new StyleRange(i, 1, null, null, SWT.NORMAL);}switch (style) {case BOLD:newStyle.fontStyle ^= SWT.BOLD;break;case ITALIC:newStyle.fontStyle ^= SWT.ITALIC;break;case STRIKE_THROUGH:newStyle.strikeout = !newStyle.strikeout;break;case UNDERLINE:newStyle.underline = !newStyle.underline;break;}styledText.setStyleRange(newStyle);}styledText.setSelectionRange(sel.x + sel.y, 0);}/*** Clear all styled data*/protected void clearStylesFromSelection() {Point sel = styledText.getSelectionRange();if ((sel != null) && (sel.y != 0)) {StyleRange style = new StyleRange(sel.x, sel.y, null, null, SWT.NORMAL);styledText.setStyleRange(style);}styledText.setSelectionRange(sel.x + sel.y, 0);}private Integer[] getLineBreaks() {List list = new ArrayList();int lastIdx = 0;while (lastIdx < styledText.getCharCount()) {int br = styledText.getText().indexOf(styledText.getLineDelimiter(), lastIdx);if (br >= lastIdx && !list.contains(br)) {list.add(br);}lastIdx += styledText.getLineDelimiter().length() + 1;}Collections.sort(list);return list.toArray(new Integer[list.size()]);}protected void handleCutCopy() {// Save the cut/copied style info so that during paste we will maintain// the style information. Cut/copied text is put in the clipboard in// RTF format, but is not pasted in RTF format. The other way to// handle the pasting of styles would be to access the Clipboard// directly and// parse the RTF text.cachedStyles = Collections.synchronizedList(new LinkedList());Point sel = styledText.getSelectionRange();int startX = sel.x;for (int i = sel.x; i <= sel.x + sel.y - 1; i++) {StyleRange style = styledText.getStyleRangeAtOffset(i);if (style != null) {style.start = style.start - startX;if (!cachedStyles.isEmpty()) {StyleRange lastStyle = cachedStyles.get(cachedStyles.size() - 1);if (lastStyle.similarTo(style)&& lastStyle.start + lastStyle.length == style.start) {lastStyle.length++;} else {cachedStyles.add(style);}} else {cachedStyles.add(style);}}}pasteBtn.setEnabled(true);}private void handleExtendedModified(ExtendedModifyEvent event) {if (event.length == 0) return;StyleRange style;if (event.length == 1|| styledText.getTextRange(event.start, event.length).equals(styledText.getLineDelimiter())) {// Have the new text take on the style of the text to its right// (during// typing) if no style information is active.int caretOffset = styledText.getCaretOffset();style = null;if (caretOffset < styledText.getCharCount())style = styledText.getStyleRangeAtOffset(caretOffset);if (style != null) {style = (StyleRange) style.clone();style.start = event.start;style.length = event.length;} else {style = new StyleRange(event.start, event.length, null, null,SWT.NORMAL);}if (boldBtn.getSelection())style.fontStyle |= SWT.BOLD;if (italicBtn.getSelection())style.fontStyle |= SWT.ITALIC;style.underline = underlineBtn.getSelection();style.strikeout = strikeThroughBtn.getSelection();if (!style.isUnstyled())styledText.setStyleRange(style);} else {// paste occurring, have text take on the styles it had when it was// cut/copiedfor (int i = 0; i < cachedStyles.size(); i++) {style = cachedStyles.get(i);StyleRange newStyle = (StyleRange) style.clone();newStyle.start = style.start + event.start;styledText.setStyleRange(newStyle);}}}private void handleTextSelected(SelectionEvent event) {Point sel = styledText.getSelectionRange();if ((sel != null) && (sel.y != 0)) {StyleRange[] styles = styledText.getStyleRanges(sel.x, sel.y);eraserBtn.setEnabled((styles != null) && (styles.length > 0));} else {eraserBtn.setEnabled(false);}}private void handleKeyReleased(KeyEvent event) {if ((event.keyCode == SWT.ARROW_LEFT) || (event.keyCode == SWT.ARROW_UP)|| (event.keyCode == SWT.ARROW_RIGHT) || (event.keyCode == SWT.ARROW_DOWN)) {updateStyleButtons();}}private void updateStyleButtons() {int caretOffset = styledText.getCaretOffset();StyleRange style = null;if (caretOffset >= 0 && caretOffset < styledText.getCharCount()) {style = styledText.getStyleRangeAtOffset(caretOffset);}if (style != null) {boldBtn.setSelection((style.fontStyle & SWT.BOLD) != 0);italicBtn.setSelection((style.fontStyle & SWT.ITALIC) != 0);underlineBtn.setSelection(style.underline);strikeThroughBtn.setSelection(style.strikeout);} else {boldBtn.setSelection(false);italicBtn.setSelection(false);underlineBtn.setSelection(false);strikeThroughBtn.setSelection(false);}}private void initComponents() {GridLayout layout = new GridLayout();layout.numColumns = 1;setLayout(layout);toolBar = createToolBar(this);toolBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));styledText = new StyledText(this, SWT.BORDER | SWT.MULTI |SWT.V_SCROLL | SWT.H_SCROLL);styledText.setLayoutData(new GridData(GridData.FILL_BOTH));styledText.addKeyListener(new KeyAdapter() {@Overridepublic void keyReleased(KeyEvent e) {handleKeyReleased(e);}});styledText.addExtendedModifyListener(new ExtendedModifyListener() {@Overridepublic void modifyText(ExtendedModifyEvent event) {handleExtendedModified(event);}});styledText.addMouseListener(new MouseAdapter() {@Overridepublic void mouseUp(MouseEvent e) {updateStyleButtons();}});styledText.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent event) {handleTextSelected(event);}});}private ToolBar createToolBar(Composite parent) {ToolBar toolBar = new ToolBar(parent, SWT.FLAT);boldBtn = new ToolItem(toolBar, SWT.CHECK);boldBtn.setImage(RichTextImages.IMG_BOLD);boldBtn.setToolTipText(RichTextStrings.boldBtn_tooltipText);boldBtn.addSelectionListener(new FontStyleButtonListener(FontStyle.BOLD));italicBtn = new ToolItem(toolBar, SWT.CHECK);italicBtn.setImage(RichTextImages.IMG_ITALIC);italicBtn.setToolTipText(RichTextStrings.italicBtn_tooltipText);italicBtn.addSelectionListener(new FontStyleButtonListener(FontStyle.ITALIC));underlineBtn = new ToolItem(toolBar, SWT.CHECK);underlineBtn.setImage(RichTextImages.IMG_UNDERLINE);underlineBtn.setToolTipText(RichTextStrings.underlineBtn_tooltipText);underlineBtn.addSelectionListener(new FontStyleButtonListener(FontStyle.UNDERLINE));strikeThroughBtn = new ToolItem(toolBar, SWT.CHECK);strikeThroughBtn.setImage(RichTextImages.IMG_STRIKE_THROUGH);strikeThroughBtn.setToolTipText(RichTextStrings.strikeThroughBtn_tooltipText);strikeThroughBtn.addSelectionListener(new FontStyleButtonListener(FontStyle.STRIKE_THROUGH));new ToolItem(toolBar, SWT.SEPARATOR);ToolItem cutBtn = new ToolItem(toolBar, SWT.PUSH);cutBtn.setImage(RichTextImages.IMG_CUT);cutBtn.setToolTipText(RichTextStrings.cutBtn_tooltipText);cutBtn.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {handleCutCopy();styledText.cut();}});ToolItem copyBtn = new ToolItem(toolBar, SWT.PUSH);copyBtn.setImage(RichTextImages.IMG_COPY);copyBtn.setToolTipText(RichTextStrings.copyBtn_tooltipText);copyBtn.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {handleCutCopy();styledText.copy();}});pasteBtn = new ToolItem(toolBar, SWT.PUSH);pasteBtn.setEnabled(false);pasteBtn.setImage(RichTextImages.IMG_PASTE);pasteBtn.setToolTipText(RichTextStrings.pasteBtn_tooltipText);pasteBtn.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {styledText.paste();}});new ToolItem(toolBar, SWT.SEPARATOR);eraserBtn = new ToolItem(toolBar, SWT.PUSH);eraserBtn.setEnabled(false);eraserBtn.setImage(RichTextImages.IMG_ERASER);eraserBtn.setToolTipText(RichTextStrings.eraserBtn_tooltipText);eraserBtn.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {clearStylesFromSelection();}});return toolBar;}private List translateStyle(StyleRange range) {List list = new ArrayList();if ((range.fontStyle & SWT.BOLD) != 0) {list.add(FontStyle.BOLD);}if ((range.fontStyle & SWT.ITALIC) != 0) {list.add(FontStyle.ITALIC);}if (range.strikeout) {list.add(FontStyle.STRIKE_THROUGH);}if (range.underline) {list.add(FontStyle.UNDERLINE);}return list;}private class FontStyleButtonListener extends SelectionAdapter {private FontStyle style;public FontStyleButtonListener(FontStyle style) {this.style = style;}@Overridepublic void widgetSelected(SelectionEvent e) {applyFontStyleToSelection(style);}}}
如您所见,我们的RichText控件基本上是ToolBar和StyledText组件的包装,具有不同事件侦听器的这两个控件都将这两个控件挂钩。  
支持班
在本节中,我将显示用于实现富文本编辑器控件使用的一些支持类的代码。 我将在这里省略为控件提供图像和本地化字符串的类,因为那里有太多关于如何在SWT中进行操作的示例,我将重点介绍格式化和解析控件的输出/输入所需的类。
首先是一个Java枚举,将用于标识支持的不同字体样式:
public enum FontStyle {BOLD, ITALIC, STRIKE_THROUGH, UNDERLINE
}

下一个称为RichStringBuilder,它将用作帮助程序类,以将StyledText组件的内容格式化为基本HTML:

import java.util.Stack;public final class RichStringBuilder {public static final String LINE_DELIMITER = "<br/>";private StringBuilder builder;private Stack fontStyleStack;public RichStringBuilder() {builder = new StringBuilder();fontStyleStack = new Stack();}public RichStringBuilder append(String text) {builder.append(text);return this;}public RichStringBuilder appendLineBreak() {builder.append(LINE_DELIMITER);return this;}public RichStringBuilder startParagraph() {builder.append("<p>");return this;}public RichStringBuilder startFontStyle(FontStyle fontStyle) {fontStyleStack.push(fontStyle);internalStartFontStyle(fontStyle);return this;}public RichStringBuilder startFontStyles(FontStyle... fontStyles) {for (FontStyle fs : fontStyles) {startFontStyle(fs);}return this;}public RichStringBuilder endFontStyles(int count) {for (int i = 0;i < count;i++) {endStyle();}return this;}public RichStringBuilder endStyle() {if (fontStyleStack.size() > 0) {FontStyle style = fontStyleStack.pop();internalEndFontStyle(style);}return this;}public RichStringBuilder endParagraph() {flushStyles();builder.append("</p>");return this;}public void flushStyles() {while (fontStyleStack.size() > 0) {endStyle();}}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (null == o) return false;if (!(o instanceof RichStringBuilder)) return false;return ((RichStringBuilder) o).builder.equals(builder);}@Overridepublic int hashCode() {return builder.hashCode();}@Overridepublic String toString() {return builder.toString();}private void internalStartFontStyle(FontStyle fontStyle) {switch (fontStyle) {case BOLD:builder.append("<b>");break;case ITALIC:builder.append("<i>");break;case STRIKE_THROUGH:builder.append("<del>");break;case UNDERLINE:builder.append("<ins>");break;}}private void internalEndFontStyle(FontStyle fontStyle) {switch (fontStyle) {case BOLD:builder.append("</b>");break;case ITALIC:builder.append("</i>");break;case STRIKE_THROUGH:builder.append("</del>");break;case UNDERLINE:builder.append("</ins>");break;}}}

第三个是基于SAX的内容处理程序,它将基本HTML解析为StyledText控件时将启动事件:

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;public final class RichTextParser {public static RichTextParser parse(String formattedText)throws ParserConfigurationException, SAXException, IOException {return new RichTextParser(formattedText);}private StringBuilder text = new StringBuilder();private List styleRanges = new ArrayList();private RichTextParser(String formattedText)throws ParserConfigurationException, SAXException, IOException {StringReader reader = new StringReader(formattedText);SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();DefaultHandler handler = new RichTextContentHandler();parser.parse(new InputSource(reader), handler);}public String getText() {return text.toString();}public StyleRange[] getStyleRanges() {return styleRanges.toArray(new StyleRange[styleRanges.size()]);}private class RichTextContentHandler extends DefaultHandler {private Stack<List> stylesStack = new Stack<List>();private String lastTextChunk = null;@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {lastTextChunk = new String(ch, start, length);}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// If there is not any previous text chunk parsed then returnif (lastTextChunk == null) return;// If the tag found is not a supported one then returnif (!"p".equals(qName) || !"b".equals(qName) || !"i".equals(qName) ||!"ins".equals(qName) || !"del".equals(qName)) {return;}List lastStyles = lastFontStyles(true);if (lastStyles != null) {StyleRange range = transform(lastStyles);range.start = currentIndex() + 1;range.length = lastTextChunk.length();styleRanges.add(range);}text.append(lastTextChunk);lastTextChunk = null;}@Overridepublic void startElement(String uri, String localName, String qName,Attributes atts) throws SAXException {// If the tag found is not a supported one then returnif (!"p".equals(qName) || !"b".equals(qName) || !"i".equals(qName) ||!"ins".equals(qName) || !"del".equals(qName)) {return;}List lastStyles = lastFontStyles(false);if (lastTextChunk == null) {if (lastStyles == null) {lastStyles = new ArrayList();stylesStack.add(lastStyles);}} else {if (lastStyles != null) {StyleRange range = transform(lastStyles);range.start = currentIndex() + 1;range.length = lastTextChunk.length();styleRanges.add(range);}text.append(lastTextChunk);lastTextChunk = null;}if ("b".equals(qName)) {lastStyles.add(FontStyle.BOLD);} else if ("i".equals(qName)) {lastStyles.add(FontStyle.ITALIC);} else if ("ins".equals(qName)) {lastStyles.add(FontStyle.UNDERLINE);} else {lastStyles.add(FontStyle.STRIKE_THROUGH);}}private StyleRange transform(List styles) {StyleRange range = new StyleRange();range.start = currentIndex() + 1;range.length = lastTextChunk.length();for (FontStyle fs : styles) {if (FontStyle.BOLD == fs) {range.fontStyle = (range.fontStyle & SWT.BOLD);} else if (FontStyle.ITALIC == fs) {range.fontStyle = (range.fontStyle & SWT.ITALIC);} else if (FontStyle.STRIKE_THROUGH == fs) {range.strikeout = true;} else if (FontStyle.UNDERLINE == fs) {range.underline = true;}}return range;}private List lastFontStyles(boolean remove) {List lastStyles = null;if (stylesStack.size() > 0) {if (remove) {lastStyles = stylesStack.pop();} else {lastStyles = stylesStack.peek();}}return lastStyles;}private int currentIndex() {return text.length() - 1;}}}
结论
实现您自己的SWT RichText控件可能不是满足您需求的最佳选择,您将需要权衡这样做的利弊,以及是否有必要投资其中一种现成的商业解决方案。 但是,我想通过这篇文章来演示如何在SWT对话框和视图中嵌入您自己的(简单且轻量级的)富文本编辑器,与从中获得的好处相比,它很容易实现并且需要花费很少的精力。
参考:来自Code Nibbles博客的JCG合作伙伴 Alonso Dominguez的RichText编辑器组件,用于基于SWT的应用程序 。

翻译自: https://www.javacodegeeks.com/2012/07/richtext-editor-component-for-swt-based.html

小程序richtext

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353909.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《重构-改善既有代码的设计》学习笔记(一)

其实看了重构之后&#xff0c;发现重构和设计模式有很多很多相通的地方&#xff0c;或者有着同样的目的。你完全可以参考设计模式的原则来修改已有的代码。 1.单一职责原则 2.开放--封闭原则 3.依赖倒装原则 4.迪米特原则&#xff08;类松耦合&#xff09; 笔者也在《重构》这本…

展示Java开发人员课程包

60个小时以上的课程&#xff0c;5门所有级别的课程&#xff1a;成为Java编程专家 嘿&#xff0c;怪胎&#xff0c; 本周&#xff0c;在我们的JCG Deals商店中 &#xff0c;我们提供了一个极端的报价 。 我们提供的Java Developer Course Bundle 仅售39美元&#xff0c;而不是…

吃鸡服务器不接受响应,绝地求生:蓝洞优化服务器性能,从此告别掉帧延迟!...

原标题&#xff1a;绝地求生:蓝洞优化服务器性能&#xff0c;从此告别掉帧延迟&#xff01;很多玩家们都非常了解服务器的重要性&#xff0c;服务器响应时间也可以描述为‘网络延迟’。如果服务器的响应时间减少(或者网络延迟减少) 的话&#xff0c;玩家们可以体验到更加顺畅的…

遍历List过程中同时修改

public static void Main(){List<int> list new List<int>();int[] a{0,1,2,3,4,5,6,7,8,9};list.AddRange(a);foreach (var i in list){Console.WriteLine(i);if (i 2){list.Remove(i);}}Console.Read();} 有一个需求&#xff0c;要对List边遍历边将符合条件的L…

fifa15服务器位置,《FIFA 15》全系统教程图文攻略

《FIFA 15》全系统教程图文攻略2014-09-23 11:04:14来源&#xff1a;3DM论坛编辑&#xff1a;评论(0)《FIFA 15》为EA旗下足球模拟游戏&#xff0c;游戏使用了《UFC》所使用的EA的Ignite引擎&#xff0c;球员的全身细节、动作以及物理破坏效果都相当到位&#xff0c;将给带给玩…

Java EE 8 MVC:全局异常处理

在之前的先前文章中&#xff0c;我们了解了在Java EE MVC中访问请求信息&#xff08;例如查询或路径参数 &#xff09;的各种方法。 这篇文章显示了如何将全局异常处理应用于MVC应用程序。 假设我们有一个控制器方法可能抛出IllegalArgumentException&#xff1a; Controller…

可以显示网页服务器或者文件系统,浏览器是指可以显示网页服务器或者文件系统的HTML文件(标准通用标记语言的一个应用)内容,并让用户与这些文件交互的一种软件...

参考答案如下浏览技术进步有哪些类型&#xff1f;它们对贸易条件有什么影响&#xff1f;OSPF 协议生成的路由分为四类&#xff0c;指可准通些种软按优先级从高到低顺序来说分别是&#xff1a;区域内路由、区域间路由、第一类外部路由、第二类外部路由。并不是所有的商品都适合于…

hdu 3016 Man Down

题意&#xff1a;给你n个板子&#xff0c;初始100生命&#xff0c;到达每个板子加血或者扣血&#xff0c;求从最上面的板子落到地面的最优解 题解&#xff1a;对于每一个木板&#xff0c;只有从左下或者从右下&#xff0c;所以从下往上来看&#xff0c;到达第n个木板的最优解为…

主机做服务器共享文件,主机做文件共享服务器

主机做文件共享服务器 内容精选换一换用户要使用CSG&#xff0c;首先要注册一个华为云帐号&#xff0c;才有访问华为云资源的权限。目前CSG服务处于公测阶段&#xff0c;需要申请公测并通过审核才能使用&#xff0c;商用后自动开通。此外为确保用户能正确快速使用CSG服务&#…

java nosql_使用NoSQL实现实体服务–第4部分:Java EE

java nosql现在&#xff0c;我已经准备好了一个框架式的合同优先型Web服务&#xff0c;并使用Ektorp和CouchDB创建了一个数据访问层 &#xff0c;是时候将它们连接到一个可以正常工作的实体服务中了 。 为此&#xff0c;我将使用Java EE和Glassfish 3.1。 值得注意的是&#xf…

iOS安装CocoaPods的详细步骤

之前的文章没有说明如何安装CocoaPods&#xff0c;现在向大家一一说明&#xff1a; 1.升级ruby环境 应该输入&#xff1a;$ sudo gem update --system sudo是强制升级 2.更换ruby镜像 首先先移除现有ruby镜像&#xff1a;终端输入&#xff1a;$ gem sources --remove https://r…

i7怎么老是显示无服务器,i7处理器真有这么差?网友:懂电脑的人都不买!

大家都知道i7处理器的性能非常强劲&#xff0c;但是很多人买电脑时却选择i5或者AMD的&#xff0c;这是为什么&#xff1f;仅仅是价格原因么&#xff1f;可是为什么即使是预算足够&#xff0c;那些懂电脑的人也不会去选择I7处理器&#xff0c;难道名声在外的i7处理器真有这么差&…

JQuery入门

jQuery基础语法 $(selector).action() 查找标签 选择器 id选择器&#xff1a; $("#id") 标签选择器&#xff1a; $("tagName") class选择器&#xff1a; $(".className") 配合使用&#xff1a; $("div.c1") // 找到有c1 class类的div…

Java应用程序的令牌认证

建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 2016年5月12日更新&#xff1a;构建…

mac 远程ftp服务器文件共享,mac 远程ftp服务器文件

mac 远程ftp服务器文件 内容精选换一换云堡垒机配置了FTP/SFTP远程备份&#xff0c;报请检查服务器密码或网络连接情况错误&#xff0c;不能启动远程备份。选择备份具体某一天日志&#xff0c;提示备份正在执行&#xff0c;但远程服务器未接收到该备份文件。原因一&#xff1a;…

ConcurrentHashMap 源码分析

https://weibo.com/6515091862/G9DawzK9fhttps://weibo.com/6515091862/G9D6x1kQrhttps://weibo.com/6515091862/G9Bo8oRCp 1. 前言 终于到这个类了&#xff0c;其实在前面很过很多次这个类&#xff0c;因为这个类代码量比较大&#xff0c;并且涉及到并发的问题&#xff0c;还有…

lambda ::_Lambda项目:迈向多核及超越

lambda ::周一下午在JavaOne 2011的希尔顿旧金山大宴会厅B上做了“ Project Lambda&#xff1a;迈向多核和超越”&#xff08;会议27400&#xff0c;不要与Brian Goetz的同名演讲相混淆&#xff09; 的演示 。大宴会厅关闭&#xff0c;这是一个非常大型的非主题演讲场地&#x…

Java 8:默认方法解析规则

随着Java 8中默认方法的引入&#xff0c;一个类现在可以从多个位置&#xff08;例如另一个类或接口&#xff09;继承相同的方法。 在这种情况下&#xff0c;可以使用以下规则来确定选择哪种方法&#xff1a; 类或超类方法声明始终优先于默认方法 否则&#xff0c;将使用具有最…

Log4j 2使用教程二 【详解】

配置Log4j 2的配置可以通过4种方式中的1种完成&#xff1a;1、通过使用XML&#xff0c;JSON&#xff0c;YAML或属性格式编写的配置文件。 2、以编程方式&#xff0c;通过创建一个ConfigurationFactory和配置实现。 3、以编程方式&#xff0c;通过调用配置界面中公开的API将组件…

firstJava

import java.util.Date;/*** Created by Administrator on 2018/3/30.*/ public class Test {public static void main(String[] args) {System.out.println("强调自主练习");new Date();} } 转载于:https://www.cnblogs.com/fengdaren/p/8675148.html